@bitgo-beta/sdk-coin-algo 1.3.3-alpha.43 → 1.3.3-alpha.430
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/algo.d.ts +117 -16
- package/dist/src/algo.d.ts.map +1 -1
- package/dist/src/algo.js +430 -46
- package/dist/src/algoToken.d.ts +1 -1
- package/dist/src/algoToken.d.ts.map +1 -1
- package/dist/src/algoToken.js +3 -3
- package/dist/src/index.js +23 -9
- package/dist/src/lib/assetTransferBuilder.d.ts +1 -1
- package/dist/src/lib/assetTransferBuilder.js +2 -2
- package/dist/src/lib/ifaces.d.ts +0 -1
- package/dist/src/lib/ifaces.d.ts.map +1 -1
- package/dist/src/lib/index.js +23 -9
- package/dist/src/lib/keyPair.js +24 -10
- package/dist/src/lib/keyRegistrationBuilder.js +1 -1
- package/dist/src/lib/seedEncoding.js +23 -9
- package/dist/src/lib/transaction.js +3 -4
- package/dist/src/lib/transactionBuilder.d.ts +6 -0
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
- package/dist/src/lib/transactionBuilder.js +45 -29
- package/dist/src/lib/transactionBuilderFactory.js +1 -1
- package/dist/src/lib/transferBuilder.js +1 -1
- package/dist/src/lib/txnSchema.js +1 -1
- package/dist/src/lib/utils.d.ts +6 -1
- package/dist/src/lib/utils.d.ts.map +1 -1
- package/dist/src/lib/utils.js +35 -11
- package/dist/src/seedValidator.js +23 -9
- package/dist/test/fixtures/algo.d.ts +101 -0
- package/dist/test/fixtures/algo.d.ts.map +1 -0
- package/dist/test/fixtures/algo.js +239 -0
- package/dist/test/fixtures/resources.d.ts +121 -0
- package/dist/test/fixtures/resources.d.ts.map +1 -0
- package/dist/test/fixtures/resources.js +131 -0
- package/dist/test/integration/algo.integration.d.ts +2 -0
- package/dist/test/integration/algo.integration.d.ts.map +1 -0
- package/dist/test/integration/algo.integration.js +71 -0
- package/dist/test/unit/algo.d.ts +2 -0
- package/dist/test/unit/algo.d.ts.map +1 -0
- package/dist/test/unit/algo.js +1223 -0
- package/dist/test/unit/algoIsWalletAddress.d.ts +2 -0
- package/dist/test/unit/algoIsWalletAddress.d.ts.map +1 -0
- package/dist/test/unit/algoIsWalletAddress.js +118 -0
- package/dist/test/unit/algoToken.d.ts +2 -0
- package/dist/test/unit/algoToken.d.ts.map +1 -0
- package/dist/test/unit/algoToken.js +79 -0
- package/dist/test/unit/fixtures/algoBackupKey.d.ts +4 -0
- package/dist/test/unit/fixtures/algoBackupKey.d.ts.map +1 -0
- package/dist/test/unit/fixtures/algoBackupKey.js +10 -0
- package/dist/test/unit/lib/keyPair.d.ts +2 -0
- package/dist/test/unit/lib/keyPair.d.ts.map +1 -0
- package/dist/test/unit/lib/keyPair.js +110 -0
- package/dist/test/unit/lib/seedEncoding.d.ts +2 -0
- package/dist/test/unit/lib/seedEncoding.d.ts.map +1 -0
- package/dist/test/unit/lib/seedEncoding.js +59 -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 +157 -0
- package/dist/test/unit/lib/transactionBuilder/assetTransferBuilder.d.ts +2 -0
- package/dist/test/unit/lib/transactionBuilder/assetTransferBuilder.d.ts.map +1 -0
- package/dist/test/unit/lib/transactionBuilder/assetTransferBuilder.js +300 -0
- package/dist/test/unit/lib/transactionBuilder/base.d.ts +2 -0
- package/dist/test/unit/lib/transactionBuilder/base.d.ts.map +1 -0
- package/dist/test/unit/lib/transactionBuilder/base.js +310 -0
- package/dist/test/unit/lib/transactionBuilder/keyRegistrationBuilder.d.ts +2 -0
- package/dist/test/unit/lib/transactionBuilder/keyRegistrationBuilder.d.ts.map +1 -0
- package/dist/test/unit/lib/transactionBuilder/keyRegistrationBuilder.js +473 -0
- package/dist/test/unit/lib/transactionBuilder/transactionBuilderFactory.d.ts +2 -0
- package/dist/test/unit/lib/transactionBuilder/transactionBuilderFactory.d.ts.map +1 -0
- package/dist/test/unit/lib/transactionBuilder/transactionBuilderFactory.js +138 -0
- package/dist/test/unit/lib/transactionBuilder/transferBuilder.d.ts +2 -0
- package/dist/test/unit/lib/transactionBuilder/transferBuilder.d.ts.map +1 -0
- package/dist/test/unit/lib/transactionBuilder/transferBuilder.js +290 -0
- package/dist/test/unit/lib/utils.d.ts +2 -0
- package/dist/test/unit/lib/utils.d.ts.map +1 -0
- package/dist/test/unit/lib/utils.js +307 -0
- package/dist/test/unit/verifyTransaction.d.ts +2 -0
- package/dist/test/unit/verifyTransaction.d.ts.map +1 -0
- package/dist/test/unit/verifyTransaction.js +703 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +12 -10
- package/.eslintignore +0 -5
- package/.mocharc.yml +0 -8
- package/CHANGELOG.md +0 -160
- package/types/index.d.ts +0 -60
|
@@ -0,0 +1,1223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const src_1 = require("../../src");
|
|
40
|
+
const sdk_test_1 = require("@bitgo-beta/sdk-test");
|
|
41
|
+
const sdk_api_1 = require("@bitgo-beta/sdk-api");
|
|
42
|
+
const AlgoResources = __importStar(require("../fixtures/algo"));
|
|
43
|
+
const crypto_1 = require("crypto");
|
|
44
|
+
const statics_1 = require("@bitgo-beta/statics");
|
|
45
|
+
const sinon_1 = __importStar(require("sinon"));
|
|
46
|
+
const assert_1 = __importDefault(require("assert"));
|
|
47
|
+
const algo_1 = require("../../src/algo");
|
|
48
|
+
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
49
|
+
const lib_1 = require("../../src/lib");
|
|
50
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
51
|
+
const algoBackupKey_1 = require("./fixtures/algoBackupKey");
|
|
52
|
+
const nock_1 = __importDefault(require("nock"));
|
|
53
|
+
describe('ALGO:', function () {
|
|
54
|
+
let bitgo;
|
|
55
|
+
let basecoin;
|
|
56
|
+
const receiver = AlgoResources.accounts.account2;
|
|
57
|
+
before(function () {
|
|
58
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
|
|
59
|
+
bitgo.safeRegister('talgo', src_1.Talgo.createInstance);
|
|
60
|
+
bitgo.initializeTestVars();
|
|
61
|
+
basecoin = bitgo.coin('talgo');
|
|
62
|
+
});
|
|
63
|
+
describe('Should Fail: ', () => {
|
|
64
|
+
it('Does not have a txHex', async () => {
|
|
65
|
+
await basecoin
|
|
66
|
+
.explainTransaction({
|
|
67
|
+
params: {},
|
|
68
|
+
})
|
|
69
|
+
.should.be.rejectedWith('missing explain tx parameters');
|
|
70
|
+
});
|
|
71
|
+
it('Does not have a fee', async () => {
|
|
72
|
+
await basecoin
|
|
73
|
+
.explainTransaction({
|
|
74
|
+
params: {
|
|
75
|
+
txHex: 'Some Valid Hex',
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
.should.be.rejectedWith('missing explain tx parameters');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe('Transfer Builder: ', () => {
|
|
82
|
+
const buildBaseTransferTransaction = ({ destination, amount = 10000, sender, memo = '' }) => {
|
|
83
|
+
const factory = new src_1.AlgoLib.TransactionBuilderFactory(statics_1.coins.get('algo'));
|
|
84
|
+
const txBuilder = factory.getTransferBuilder();
|
|
85
|
+
const lease = new Uint8Array((0, crypto_1.randomBytes)(32));
|
|
86
|
+
const note = new Uint8Array(Buffer.from(memo, 'utf-8'));
|
|
87
|
+
txBuilder
|
|
88
|
+
.sender({ address: sender })
|
|
89
|
+
.to({ address: destination })
|
|
90
|
+
.amount(amount)
|
|
91
|
+
.isFlatFee(true)
|
|
92
|
+
.fee({
|
|
93
|
+
fee: '1000',
|
|
94
|
+
})
|
|
95
|
+
.firstRound(1)
|
|
96
|
+
.lastRound(100)
|
|
97
|
+
.lease(lease)
|
|
98
|
+
.note(note)
|
|
99
|
+
.testnet();
|
|
100
|
+
return txBuilder;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Build an unsigned account-lib single-signature send transaction
|
|
104
|
+
* @param sender The senders address
|
|
105
|
+
* @param destination The destination address of the transaction
|
|
106
|
+
* @param amount The amount to send to the recipient
|
|
107
|
+
* @param memo Optional note with the transaction
|
|
108
|
+
*/
|
|
109
|
+
const buildUnsignedTransaction = async function ({ sender, destination, amount = 10000, memo = '' }) {
|
|
110
|
+
const txBuilder = buildBaseTransferTransaction({ sender, destination, amount, memo });
|
|
111
|
+
return await txBuilder.build();
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Build a signed account-lib single-signature send transaction
|
|
115
|
+
* @param sender The senders address
|
|
116
|
+
* @param destination The destination address of the transaction
|
|
117
|
+
* @param amount The amount to send to the recipient
|
|
118
|
+
* @param memo Optional note with the transaction
|
|
119
|
+
*/
|
|
120
|
+
const buildSignedTransaction = async function ({ sender, destination, amount = 10000, memo = '' }) {
|
|
121
|
+
const txBuilder = buildBaseTransferTransaction({ sender, destination, amount, memo });
|
|
122
|
+
txBuilder.numberOfSigners(1);
|
|
123
|
+
txBuilder.sign({ key: AlgoResources.accounts.account1.prvKey });
|
|
124
|
+
return await txBuilder.build();
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Build a multi-signed account-lib single-signature send transaction
|
|
128
|
+
* @param senders The list of senders
|
|
129
|
+
* @param destination The destination address of the transaction
|
|
130
|
+
* @param amount The amount to send to the recipient
|
|
131
|
+
* @param memo Optional note with the transaction
|
|
132
|
+
*/
|
|
133
|
+
const buildMultiSignedTransaction = async function ({ senders, destination, amount = 10000, memo = '' }) {
|
|
134
|
+
const txBuilder = buildBaseTransferTransaction({ sender: senders[0], destination, amount, memo });
|
|
135
|
+
txBuilder.numberOfSigners(2);
|
|
136
|
+
txBuilder.setSigners(senders);
|
|
137
|
+
txBuilder.sign({ key: AlgoResources.accounts.account1.prvKey });
|
|
138
|
+
txBuilder.sign({ key: AlgoResources.accounts.account3.prvKey });
|
|
139
|
+
return await txBuilder.build();
|
|
140
|
+
};
|
|
141
|
+
it('should explain an unsigned transfer transaction hex', async function () {
|
|
142
|
+
const explain = await basecoin.explainTransaction({
|
|
143
|
+
txHex: AlgoResources.explainRawTx.transfer.unsigned,
|
|
144
|
+
feeInfo: { fee: '1000' },
|
|
145
|
+
});
|
|
146
|
+
explain.outputAmount.should.equal('10000');
|
|
147
|
+
explain.outputs[0].amount.should.equal('10000');
|
|
148
|
+
explain.outputs[0].address.should.equal(receiver.address);
|
|
149
|
+
Buffer.from(explain.outputs[0].memo).toString().should.equal(AlgoResources.explainRawTx.transfer.note);
|
|
150
|
+
explain.fee.should.equal(1000);
|
|
151
|
+
explain.changeAmount.should.equal('0');
|
|
152
|
+
});
|
|
153
|
+
it('should explain a signed transfer transaction hex', async function () {
|
|
154
|
+
const explain = await basecoin.explainTransaction({
|
|
155
|
+
txHex: AlgoResources.explainRawTx.transfer.signed,
|
|
156
|
+
feeInfo: { fee: '1000' },
|
|
157
|
+
});
|
|
158
|
+
explain.outputAmount.should.equal('10000');
|
|
159
|
+
explain.outputs[0].amount.should.equal('10000');
|
|
160
|
+
explain.outputs[0].address.should.equal(receiver.address);
|
|
161
|
+
Buffer.from(explain.outputs[0].memo).toString().should.equal(AlgoResources.explainRawTx.transfer.note);
|
|
162
|
+
explain.fee.should.equal(1000);
|
|
163
|
+
explain.changeAmount.should.equal('0');
|
|
164
|
+
});
|
|
165
|
+
it('should explain a multiSig transfer transaction hex', async function () {
|
|
166
|
+
const explain = await basecoin.explainTransaction({
|
|
167
|
+
txHex: AlgoResources.explainRawTx.transfer.multiSigned,
|
|
168
|
+
feeInfo: { fee: '1000' },
|
|
169
|
+
});
|
|
170
|
+
explain.outputAmount.should.equal('10000');
|
|
171
|
+
explain.outputs[0].amount.should.equal('10000');
|
|
172
|
+
explain.outputs[0].address.should.equal(receiver.address);
|
|
173
|
+
Buffer.from(explain.outputs[0].memo).toString().should.equal(AlgoResources.explainRawTx.transfer.note);
|
|
174
|
+
explain.fee.should.equal(1000);
|
|
175
|
+
explain.changeAmount.should.equal('0');
|
|
176
|
+
});
|
|
177
|
+
it('should explain a half signed transfer transaction hex', async function () {
|
|
178
|
+
const explain = await basecoin.explainTransaction({
|
|
179
|
+
halfSigned: {
|
|
180
|
+
txHex: AlgoResources.explainRawTx.transfer.halfSigned,
|
|
181
|
+
},
|
|
182
|
+
feeInfo: { fee: '1000' },
|
|
183
|
+
});
|
|
184
|
+
explain.outputAmount.should.equal('10000');
|
|
185
|
+
explain.outputs[0].amount.should.equal('10000');
|
|
186
|
+
explain.outputs[0].address.should.equal(receiver.address);
|
|
187
|
+
Buffer.from(explain.outputs[0].memo).toString().should.equal(AlgoResources.explainRawTx.transfer.note);
|
|
188
|
+
explain.fee.should.equal(1000);
|
|
189
|
+
explain.changeAmount.should.equal('0');
|
|
190
|
+
});
|
|
191
|
+
it('should explain an unsigned transaction', async function () {
|
|
192
|
+
const sender = AlgoResources.accounts.account1.address;
|
|
193
|
+
const destination = AlgoResources.accounts.account2.address;
|
|
194
|
+
const amount = 10000;
|
|
195
|
+
const memo = AlgoResources.explainRawTx.transfer.note;
|
|
196
|
+
const unsignedTransaction = await buildUnsignedTransaction({
|
|
197
|
+
sender,
|
|
198
|
+
destination,
|
|
199
|
+
amount,
|
|
200
|
+
memo,
|
|
201
|
+
});
|
|
202
|
+
const unsignedHex = Buffer.from(unsignedTransaction.toBroadcastFormat()).toString('hex');
|
|
203
|
+
const explain = await basecoin.explainTransaction({
|
|
204
|
+
txHex: unsignedHex,
|
|
205
|
+
feeInfo: { fee: '1000' },
|
|
206
|
+
});
|
|
207
|
+
Buffer.from(explain.outputs[0].memo).toString().should.equal(AlgoResources.explainRawTx.transfer.note);
|
|
208
|
+
explain.outputs[0].amount.should.equal(amount.toString());
|
|
209
|
+
explain.outputs[0].address.should.equal(destination);
|
|
210
|
+
});
|
|
211
|
+
it('should explain a signed transaction', async function () {
|
|
212
|
+
const sender = AlgoResources.accounts.account1.address;
|
|
213
|
+
const destination = AlgoResources.accounts.account2.address;
|
|
214
|
+
const amount = 10000;
|
|
215
|
+
const memo = AlgoResources.explainRawTx.transfer.note;
|
|
216
|
+
const signedTransaction = await buildSignedTransaction({
|
|
217
|
+
sender,
|
|
218
|
+
destination,
|
|
219
|
+
amount,
|
|
220
|
+
memo,
|
|
221
|
+
});
|
|
222
|
+
const signedHex = Buffer.from(signedTransaction.toBroadcastFormat()).toString('hex');
|
|
223
|
+
const explain = await basecoin.explainTransaction({
|
|
224
|
+
txHex: signedHex,
|
|
225
|
+
feeInfo: { fee: '1000' },
|
|
226
|
+
});
|
|
227
|
+
Buffer.from(explain.outputs[0].memo).toString().should.equal(AlgoResources.explainRawTx.transfer.note);
|
|
228
|
+
explain.outputs[0].amount.should.equal(amount.toString());
|
|
229
|
+
explain.outputs[0].address.should.equal(destination);
|
|
230
|
+
});
|
|
231
|
+
it('should explain a multiSigned transaction', async function () {
|
|
232
|
+
const senders = [AlgoResources.accounts.account1.address, AlgoResources.accounts.account3.address];
|
|
233
|
+
const destination = AlgoResources.accounts.account2.address;
|
|
234
|
+
const amount = 10000;
|
|
235
|
+
const memo = AlgoResources.explainRawTx.transfer.note;
|
|
236
|
+
const signedTransaction = await buildMultiSignedTransaction({
|
|
237
|
+
senders,
|
|
238
|
+
destination,
|
|
239
|
+
amount,
|
|
240
|
+
memo,
|
|
241
|
+
});
|
|
242
|
+
const signedHex = Buffer.from(signedTransaction.toBroadcastFormat()).toString('hex');
|
|
243
|
+
const explain = await basecoin.explainTransaction({
|
|
244
|
+
txHex: signedHex,
|
|
245
|
+
feeInfo: { fee: '1000' },
|
|
246
|
+
});
|
|
247
|
+
Buffer.from(explain.outputs[0].memo).toString().should.equal(AlgoResources.explainRawTx.transfer.note);
|
|
248
|
+
explain.outputs[0].amount.should.equal(amount.toString());
|
|
249
|
+
explain.outputs[0].address.should.equal(destination);
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
describe('Asset Transfer Builder: ', () => {
|
|
253
|
+
const buildBaseAssetTransferTransaction = ({ destination, amount = 1000, tokenId, sender }) => {
|
|
254
|
+
const factory = new src_1.AlgoLib.TransactionBuilderFactory(statics_1.coins.get('algo'));
|
|
255
|
+
const txBuilder = factory.getAssetTransferBuilder();
|
|
256
|
+
const lease = new Uint8Array((0, crypto_1.randomBytes)(32));
|
|
257
|
+
txBuilder
|
|
258
|
+
.sender({ address: sender })
|
|
259
|
+
.isFlatFee(true)
|
|
260
|
+
.fee({
|
|
261
|
+
fee: '1000',
|
|
262
|
+
})
|
|
263
|
+
.tokenId(tokenId)
|
|
264
|
+
.firstRound(1)
|
|
265
|
+
.lastRound(100)
|
|
266
|
+
.lease(lease)
|
|
267
|
+
.to({ address: destination })
|
|
268
|
+
.amount(amount)
|
|
269
|
+
.testnet();
|
|
270
|
+
return txBuilder;
|
|
271
|
+
};
|
|
272
|
+
/**
|
|
273
|
+
* Build an unsigned account-lib single-signature asset transfer transaction
|
|
274
|
+
* @param sender The senders address
|
|
275
|
+
* @param destination The destination address of the transaction
|
|
276
|
+
* @param amount The amount to send to the recipient
|
|
277
|
+
* @param tokenId The assetIndex for the token
|
|
278
|
+
*/
|
|
279
|
+
const buildUnsignedTransaction = async function ({ sender, destination, amount = 10000, tokenId }) {
|
|
280
|
+
const txBuilder = buildBaseAssetTransferTransaction({ sender, destination, amount, tokenId });
|
|
281
|
+
return await txBuilder.build();
|
|
282
|
+
};
|
|
283
|
+
/**
|
|
284
|
+
* Build a signed account-lib single-signature send transaction
|
|
285
|
+
* @param sender The senders address
|
|
286
|
+
* @param destination The destination address of the transaction
|
|
287
|
+
* @param amount The amount to send to the recipient
|
|
288
|
+
* @param tokenId The assetIndex for the token
|
|
289
|
+
*/
|
|
290
|
+
const buildSignedTransaction = async function ({ sender, destination, amount = 10000, tokenId }) {
|
|
291
|
+
const txBuilder = buildBaseAssetTransferTransaction({ sender, destination, amount, tokenId });
|
|
292
|
+
txBuilder.numberOfSigners(1);
|
|
293
|
+
txBuilder.sign({ key: AlgoResources.accounts.account1.prvKey });
|
|
294
|
+
return await txBuilder.build();
|
|
295
|
+
};
|
|
296
|
+
it('should explain an unsigned asset transfer transaction hex', async function () {
|
|
297
|
+
const explain = await basecoin.explainTransaction({
|
|
298
|
+
txHex: AlgoResources.explainRawTx.assetTransfer.unsigned,
|
|
299
|
+
feeInfo: { fee: '1000' },
|
|
300
|
+
});
|
|
301
|
+
explain.outputAmount.should.equal('1000');
|
|
302
|
+
explain.outputs[0].amount.should.equal('1000');
|
|
303
|
+
explain.outputs[0].address.should.equal(receiver.address);
|
|
304
|
+
explain.fee.should.equal(1000);
|
|
305
|
+
explain.changeAmount.should.equal('0');
|
|
306
|
+
explain.tokenId.should.equal(1);
|
|
307
|
+
});
|
|
308
|
+
it('should explain a signed asset transfer transaction hex', async function () {
|
|
309
|
+
const explain = await basecoin.explainTransaction({
|
|
310
|
+
txHex: AlgoResources.explainRawTx.assetTransfer.signed,
|
|
311
|
+
feeInfo: { fee: '1000' },
|
|
312
|
+
});
|
|
313
|
+
explain.outputAmount.should.equal('10000000000000000000');
|
|
314
|
+
explain.outputs[0].amount.should.equal('10000000000000000000');
|
|
315
|
+
explain.outputs[0].address.should.equal(receiver.address);
|
|
316
|
+
explain.fee.should.equal(1000);
|
|
317
|
+
explain.changeAmount.should.equal('0');
|
|
318
|
+
explain.tokenId.should.equal(1);
|
|
319
|
+
});
|
|
320
|
+
it('should explain an unsigned transaction', async function () {
|
|
321
|
+
const sender = AlgoResources.accounts.account1.address;
|
|
322
|
+
const destination = AlgoResources.accounts.account2.address;
|
|
323
|
+
const amount = 10000;
|
|
324
|
+
const tokenId = 1;
|
|
325
|
+
const unsignedTransaction = await buildUnsignedTransaction({
|
|
326
|
+
sender,
|
|
327
|
+
destination,
|
|
328
|
+
amount,
|
|
329
|
+
tokenId,
|
|
330
|
+
});
|
|
331
|
+
const unsignedHex = Buffer.from(unsignedTransaction.toBroadcastFormat()).toString('hex');
|
|
332
|
+
const explain = await basecoin.explainTransaction({
|
|
333
|
+
txHex: unsignedHex,
|
|
334
|
+
feeInfo: { fee: '1000' },
|
|
335
|
+
});
|
|
336
|
+
explain.outputs[0].amount.should.equal(amount.toString());
|
|
337
|
+
explain.outputs[0].address.should.equal(destination);
|
|
338
|
+
explain.tokenId.should.equal(1);
|
|
339
|
+
});
|
|
340
|
+
it('should explain a signed transaction', async function () {
|
|
341
|
+
const sender = AlgoResources.accounts.account1.address;
|
|
342
|
+
const destination = AlgoResources.accounts.account2.address;
|
|
343
|
+
const amount = 10000;
|
|
344
|
+
const tokenId = 1;
|
|
345
|
+
const signedTransaction = await buildSignedTransaction({
|
|
346
|
+
sender,
|
|
347
|
+
destination,
|
|
348
|
+
amount,
|
|
349
|
+
tokenId,
|
|
350
|
+
});
|
|
351
|
+
const signedHex = Buffer.from(signedTransaction.toBroadcastFormat()).toString('hex');
|
|
352
|
+
const explain = await basecoin.explainTransaction({
|
|
353
|
+
txHex: signedHex,
|
|
354
|
+
feeInfo: { fee: '1000' },
|
|
355
|
+
});
|
|
356
|
+
explain.outputs[0].amount.should.equal(amount.toString());
|
|
357
|
+
explain.outputs[0].address.should.equal(destination);
|
|
358
|
+
explain.tokenId.should.equal(1);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
describe('Wallet Init Builder: ', () => {
|
|
362
|
+
const buildBaseKeyRegTransaction = ({ sender, memo = '' }) => {
|
|
363
|
+
const factory = new src_1.AlgoLib.TransactionBuilderFactory(statics_1.coins.get('algo'));
|
|
364
|
+
const txBuilder = factory.getWalletInitializationBuilder();
|
|
365
|
+
const lease = new Uint8Array((0, crypto_1.randomBytes)(32));
|
|
366
|
+
const note = new Uint8Array(Buffer.from(memo, 'utf-8'));
|
|
367
|
+
txBuilder
|
|
368
|
+
.sender({ address: sender.address })
|
|
369
|
+
.isFlatFee(true)
|
|
370
|
+
.fee({
|
|
371
|
+
fee: '1000',
|
|
372
|
+
})
|
|
373
|
+
.firstRound(1)
|
|
374
|
+
.lastRound(100)
|
|
375
|
+
.lease(lease)
|
|
376
|
+
.note(note)
|
|
377
|
+
.voteKey(sender.voteKey)
|
|
378
|
+
.selectionKey(sender.selectionKey)
|
|
379
|
+
.voteFirst(1)
|
|
380
|
+
.voteLast(100)
|
|
381
|
+
.voteKeyDilution(9)
|
|
382
|
+
.testnet();
|
|
383
|
+
return txBuilder;
|
|
384
|
+
};
|
|
385
|
+
/**
|
|
386
|
+
* Build an unsigned account-lib single-signature send transaction
|
|
387
|
+
* @param sender The senders address
|
|
388
|
+
* @param memo Optional note with the transaction
|
|
389
|
+
*/
|
|
390
|
+
const buildUnsignedTransaction = async function ({ sender, memo = '' }) {
|
|
391
|
+
const txBuilder = buildBaseKeyRegTransaction({ sender, memo });
|
|
392
|
+
return await txBuilder.build();
|
|
393
|
+
};
|
|
394
|
+
/**
|
|
395
|
+
* Build a signed account-lib single-signature send transaction
|
|
396
|
+
* @param sender The senders address
|
|
397
|
+
* @param memo Optional note with the transaction
|
|
398
|
+
*/
|
|
399
|
+
const buildSignedTransaction = async function ({ sender, memo = '' }) {
|
|
400
|
+
const txBuilder = buildBaseKeyRegTransaction({ sender, memo });
|
|
401
|
+
txBuilder.numberOfSigners(1);
|
|
402
|
+
txBuilder.sign({ key: AlgoResources.accounts.account1.prvKey });
|
|
403
|
+
return await txBuilder.build();
|
|
404
|
+
};
|
|
405
|
+
/**
|
|
406
|
+
* Build a multi-signed account-lib single-signature send transaction
|
|
407
|
+
* @param senders The list of senders
|
|
408
|
+
* @param memo Optional note with the transaction
|
|
409
|
+
*/
|
|
410
|
+
const buildMultiSignedTransaction = async function ({ senders, memo = '' }) {
|
|
411
|
+
const txBuilder = buildBaseKeyRegTransaction({ sender: senders[0], memo });
|
|
412
|
+
txBuilder.numberOfSigners(2);
|
|
413
|
+
txBuilder.setSigners(senders.map(({ address }) => address));
|
|
414
|
+
txBuilder.sign({ key: AlgoResources.accounts.account1.prvKey });
|
|
415
|
+
txBuilder.sign({ key: AlgoResources.accounts.account3.prvKey });
|
|
416
|
+
return await txBuilder.build();
|
|
417
|
+
};
|
|
418
|
+
it('should explain an unsigned KeyReg transfer transaction hex', async function () {
|
|
419
|
+
const sender = AlgoResources.accounts.account1;
|
|
420
|
+
const explain = await basecoin.explainTransaction({
|
|
421
|
+
txHex: AlgoResources.explainRawTx.keyreg.unsigned,
|
|
422
|
+
feeInfo: { fee: '1000' },
|
|
423
|
+
});
|
|
424
|
+
Buffer.from(explain.memo).toString().should.equal(AlgoResources.explainRawTx.keyreg.note);
|
|
425
|
+
explain.fee.should.equal(1000);
|
|
426
|
+
explain.changeAmount.should.equal('0');
|
|
427
|
+
explain.voteKey.should.equal(sender.voteKey);
|
|
428
|
+
explain.selectionKey.should.equal(sender.selectionKey);
|
|
429
|
+
explain.voteFirst.should.equal(1);
|
|
430
|
+
explain.voteLast.should.equal(100);
|
|
431
|
+
explain.voteKeyDilution.should.equal(9);
|
|
432
|
+
});
|
|
433
|
+
it('should explain a signed transfer transaction hex', async function () {
|
|
434
|
+
const sender = AlgoResources.accounts.account1;
|
|
435
|
+
const explain = await basecoin.explainTransaction({
|
|
436
|
+
txHex: AlgoResources.explainRawTx.keyreg.signed,
|
|
437
|
+
feeInfo: { fee: '1000' },
|
|
438
|
+
});
|
|
439
|
+
Buffer.from(explain.memo).toString().should.equal(AlgoResources.explainRawTx.keyreg.note);
|
|
440
|
+
explain.fee.should.equal(1000);
|
|
441
|
+
explain.changeAmount.should.equal('0');
|
|
442
|
+
explain.voteKey.should.equal(sender.voteKey);
|
|
443
|
+
explain.selectionKey.should.equal(sender.selectionKey);
|
|
444
|
+
explain.voteFirst.should.equal(1);
|
|
445
|
+
explain.voteLast.should.equal(100);
|
|
446
|
+
explain.voteKeyDilution.should.equal(9);
|
|
447
|
+
});
|
|
448
|
+
it('should explain a multiSig transfer transaction hex', async function () {
|
|
449
|
+
const sender = AlgoResources.accounts.account1;
|
|
450
|
+
const explain = await basecoin.explainTransaction({
|
|
451
|
+
txHex: AlgoResources.explainRawTx.keyreg.multiSigned,
|
|
452
|
+
feeInfo: { fee: '1000' },
|
|
453
|
+
});
|
|
454
|
+
Buffer.from(explain.memo).toString().should.equal(AlgoResources.explainRawTx.keyreg.note);
|
|
455
|
+
explain.fee.should.equal(1000);
|
|
456
|
+
explain.changeAmount.should.equal('0');
|
|
457
|
+
explain.voteKey.should.equal(sender.voteKey);
|
|
458
|
+
explain.selectionKey.should.equal(sender.selectionKey);
|
|
459
|
+
explain.voteFirst.should.equal(1);
|
|
460
|
+
explain.voteLast.should.equal(100);
|
|
461
|
+
explain.voteKeyDilution.should.equal(9);
|
|
462
|
+
});
|
|
463
|
+
it('should explain a half signed transfer transaction hex', async function () {
|
|
464
|
+
const sender = AlgoResources.accounts.account1;
|
|
465
|
+
const explain = await basecoin.explainTransaction({
|
|
466
|
+
halfSigned: {
|
|
467
|
+
txHex: AlgoResources.explainRawTx.keyreg.halfSigned,
|
|
468
|
+
},
|
|
469
|
+
feeInfo: { fee: '1000' },
|
|
470
|
+
});
|
|
471
|
+
Buffer.from(explain.memo).toString().should.equal(AlgoResources.explainRawTx.keyreg.note);
|
|
472
|
+
explain.fee.should.equal(1000);
|
|
473
|
+
explain.changeAmount.should.equal('0');
|
|
474
|
+
explain.voteKey.should.equal(sender.voteKey);
|
|
475
|
+
explain.selectionKey.should.equal(sender.selectionKey);
|
|
476
|
+
explain.voteFirst.should.equal(1);
|
|
477
|
+
explain.voteLast.should.equal(100);
|
|
478
|
+
explain.voteKeyDilution.should.equal(9);
|
|
479
|
+
});
|
|
480
|
+
it('should explain an unsigned transaction', async function () {
|
|
481
|
+
const sender = AlgoResources.accounts.account1;
|
|
482
|
+
const memo = AlgoResources.explainRawTx.transfer.note;
|
|
483
|
+
const unsignedTransaction = await buildUnsignedTransaction({
|
|
484
|
+
sender,
|
|
485
|
+
memo,
|
|
486
|
+
});
|
|
487
|
+
const unsignedHex = Buffer.from(unsignedTransaction.toBroadcastFormat()).toString('hex');
|
|
488
|
+
const explain = await basecoin.explainTransaction({
|
|
489
|
+
txHex: unsignedHex,
|
|
490
|
+
feeInfo: { fee: '1000' },
|
|
491
|
+
});
|
|
492
|
+
Buffer.from(explain.memo).toString().should.equal(AlgoResources.explainRawTx.transfer.note);
|
|
493
|
+
explain.voteKey.should.equal(sender.voteKey);
|
|
494
|
+
explain.selectionKey.should.equal(sender.selectionKey);
|
|
495
|
+
explain.voteFirst.should.equal(1);
|
|
496
|
+
explain.voteLast.should.equal(100);
|
|
497
|
+
explain.voteKeyDilution.should.equal(9);
|
|
498
|
+
});
|
|
499
|
+
it('should explain a signed transaction', async function () {
|
|
500
|
+
const sender = AlgoResources.accounts.account1;
|
|
501
|
+
const memo = AlgoResources.explainRawTx.transfer.note;
|
|
502
|
+
const signedTransaction = await buildSignedTransaction({
|
|
503
|
+
sender,
|
|
504
|
+
memo,
|
|
505
|
+
});
|
|
506
|
+
const signedHex = Buffer.from(signedTransaction.toBroadcastFormat()).toString('hex');
|
|
507
|
+
const explain = await basecoin.explainTransaction({
|
|
508
|
+
txHex: signedHex,
|
|
509
|
+
feeInfo: { fee: '1000' },
|
|
510
|
+
});
|
|
511
|
+
Buffer.from(explain.memo).toString().should.equal(AlgoResources.explainRawTx.transfer.note);
|
|
512
|
+
explain.voteKey.should.equal(sender.voteKey);
|
|
513
|
+
explain.selectionKey.should.equal(sender.selectionKey);
|
|
514
|
+
explain.voteFirst.should.equal(1);
|
|
515
|
+
explain.voteLast.should.equal(100);
|
|
516
|
+
explain.voteKeyDilution.should.equal(9);
|
|
517
|
+
});
|
|
518
|
+
it('should explain a multiSigned transaction', async function () {
|
|
519
|
+
const senders = [AlgoResources.accounts.account1, AlgoResources.accounts.account3];
|
|
520
|
+
const memo = AlgoResources.explainRawTx.transfer.note;
|
|
521
|
+
const signedTransaction = await buildMultiSignedTransaction({
|
|
522
|
+
senders,
|
|
523
|
+
memo,
|
|
524
|
+
});
|
|
525
|
+
const signedHex = Buffer.from(signedTransaction.toBroadcastFormat()).toString('hex');
|
|
526
|
+
const explain = await basecoin.explainTransaction({
|
|
527
|
+
txHex: signedHex,
|
|
528
|
+
feeInfo: { fee: '1000' },
|
|
529
|
+
});
|
|
530
|
+
Buffer.from(explain.memo).toString().should.equal(AlgoResources.explainRawTx.transfer.note);
|
|
531
|
+
explain.voteKey.should.equal(AlgoResources.accounts.account1.voteKey);
|
|
532
|
+
explain.selectionKey.should.equal(AlgoResources.accounts.account1.selectionKey);
|
|
533
|
+
explain.voteFirst.should.equal(1);
|
|
534
|
+
explain.voteLast.should.equal(100);
|
|
535
|
+
explain.voteKeyDilution.should.equal(9);
|
|
536
|
+
});
|
|
537
|
+
});
|
|
538
|
+
describe('Sign transaction', () => {
|
|
539
|
+
it('should sign transaction', async function () {
|
|
540
|
+
const signed = await basecoin.signTransaction({
|
|
541
|
+
txPrebuild: {
|
|
542
|
+
txHex: AlgoResources.rawTx.transfer.unsigned,
|
|
543
|
+
keys: [AlgoResources.accounts.account1.pubKey.toString('hex')],
|
|
544
|
+
addressVersion: 1,
|
|
545
|
+
},
|
|
546
|
+
prv: AlgoResources.accounts.account1.prvKey,
|
|
547
|
+
});
|
|
548
|
+
signed.txHex.should.equal(AlgoResources.rawTx.transfer.signed);
|
|
549
|
+
});
|
|
550
|
+
it('should sign transaction with root key', async function () {
|
|
551
|
+
const keypair = basecoin.generateRootKeyPair(AlgoResources.accounts.account1.secretKey);
|
|
552
|
+
const signed = await basecoin.signTransaction({
|
|
553
|
+
txPrebuild: {
|
|
554
|
+
txHex: AlgoResources.rawTx.transfer.unsigned,
|
|
555
|
+
keys: [keypair.pub],
|
|
556
|
+
addressVersion: 1,
|
|
557
|
+
},
|
|
558
|
+
prv: keypair.prv,
|
|
559
|
+
});
|
|
560
|
+
signed.txHex.should.equal(AlgoResources.rawTx.transfer.signed);
|
|
561
|
+
});
|
|
562
|
+
it('should sign half signed transaction', async function () {
|
|
563
|
+
const signed = await basecoin.signTransaction({
|
|
564
|
+
txPrebuild: {
|
|
565
|
+
halfSigned: {
|
|
566
|
+
txHex: AlgoResources.rawTx.transfer.halfSigned,
|
|
567
|
+
},
|
|
568
|
+
keys: [
|
|
569
|
+
AlgoResources.accounts.account1.pubKey.toString('hex'),
|
|
570
|
+
AlgoResources.accounts.account3.pubKey.toString('hex'),
|
|
571
|
+
],
|
|
572
|
+
addressVersion: 1,
|
|
573
|
+
},
|
|
574
|
+
prv: AlgoResources.accounts.account3.prvKey,
|
|
575
|
+
});
|
|
576
|
+
signed.txHex.should.equal(AlgoResources.rawTx.transfer.multisig);
|
|
577
|
+
});
|
|
578
|
+
it('should sign half signed transaction with root key', async function () {
|
|
579
|
+
const signed = await basecoin.signTransaction({
|
|
580
|
+
txPrebuild: {
|
|
581
|
+
halfSigned: {
|
|
582
|
+
txHex: AlgoResources.rootKeyData.unsignedTx,
|
|
583
|
+
},
|
|
584
|
+
keys: [
|
|
585
|
+
AlgoResources.rootKeyData.userKeyPair.pub,
|
|
586
|
+
AlgoResources.rootKeyData.backupPub,
|
|
587
|
+
AlgoResources.rootKeyData.bitgoPub,
|
|
588
|
+
],
|
|
589
|
+
addressVersion: 1,
|
|
590
|
+
},
|
|
591
|
+
prv: AlgoResources.rootKeyData.userKeyPair.prv,
|
|
592
|
+
});
|
|
593
|
+
signed.txHex.should.deepEqual(AlgoResources.rootKeyData.halfSignedTx);
|
|
594
|
+
const factory = new lib_1.TransactionBuilderFactory(statics_1.coins.get('algo'));
|
|
595
|
+
const tx = await factory.from(signed.txHex).build();
|
|
596
|
+
const txJson = tx.toJson();
|
|
597
|
+
txJson.from.should.equal(AlgoResources.rootKeyData.senderAddress);
|
|
598
|
+
});
|
|
599
|
+
it('should verify sign params if the key array contains addresses', function () {
|
|
600
|
+
const keys = [
|
|
601
|
+
AlgoResources.accounts.account1.address,
|
|
602
|
+
AlgoResources.accounts.account2.address,
|
|
603
|
+
AlgoResources.accounts.account3.address,
|
|
604
|
+
];
|
|
605
|
+
const verifiedParams = basecoin.verifySignTransactionParams({
|
|
606
|
+
txPrebuild: {
|
|
607
|
+
txHex: AlgoResources.rawTx.transfer.unsigned,
|
|
608
|
+
keys,
|
|
609
|
+
addressVersion: 1,
|
|
610
|
+
},
|
|
611
|
+
prv: AlgoResources.accounts.account2.secretKey.toString('hex'),
|
|
612
|
+
});
|
|
613
|
+
verifiedParams.should.have.properties([
|
|
614
|
+
'txHex',
|
|
615
|
+
'addressVersion',
|
|
616
|
+
'signers',
|
|
617
|
+
'prv',
|
|
618
|
+
'isHalfSigned',
|
|
619
|
+
'numberSigners',
|
|
620
|
+
]);
|
|
621
|
+
const { txHex, signers, isHalfSigned } = verifiedParams;
|
|
622
|
+
txHex.should.be.equal(AlgoResources.rawTx.transfer.unsigned);
|
|
623
|
+
signers.should.be.deepEqual(keys);
|
|
624
|
+
isHalfSigned.should.be.equal(false);
|
|
625
|
+
});
|
|
626
|
+
it('should sign half signed transaction if the key array contains addresses', async function () {
|
|
627
|
+
const signed = await basecoin.signTransaction({
|
|
628
|
+
txPrebuild: {
|
|
629
|
+
halfSigned: {
|
|
630
|
+
txHex: AlgoResources.rawTx.transfer.halfSigned,
|
|
631
|
+
},
|
|
632
|
+
keys: [AlgoResources.accounts.account1.address, AlgoResources.accounts.account3.address],
|
|
633
|
+
addressVersion: 1,
|
|
634
|
+
},
|
|
635
|
+
prv: AlgoResources.accounts.account3.prvKey,
|
|
636
|
+
});
|
|
637
|
+
signed.txHex.should.equal(AlgoResources.rawTx.transfer.multisig);
|
|
638
|
+
});
|
|
639
|
+
});
|
|
640
|
+
describe('Sign message', () => {
|
|
641
|
+
it('should sign message', async function () {
|
|
642
|
+
const signed = await basecoin.signMessage({ prv: AlgoResources.accounts.account1.prvKey }, AlgoResources.message.unsigned);
|
|
643
|
+
signed.toString('hex').should.equal(AlgoResources.message.signed);
|
|
644
|
+
});
|
|
645
|
+
});
|
|
646
|
+
describe('Generate wallet key pair: ', () => {
|
|
647
|
+
it('should generate key pair', () => {
|
|
648
|
+
const kp = basecoin.generateKeyPair();
|
|
649
|
+
basecoin.isValidPub(kp.pub).should.equal(true);
|
|
650
|
+
basecoin.isValidPrv(kp.prv).should.equal(true);
|
|
651
|
+
});
|
|
652
|
+
it('should generate key pair from seed', () => {
|
|
653
|
+
const seed = Buffer.from('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', 'hex');
|
|
654
|
+
const kp = basecoin.generateKeyPair(seed);
|
|
655
|
+
basecoin.isValidPub(kp.pub).should.equal(true);
|
|
656
|
+
basecoin.isValidPrv(kp.prv).should.equal(true);
|
|
657
|
+
});
|
|
658
|
+
});
|
|
659
|
+
describe('Generate wallet Root key pair: ', () => {
|
|
660
|
+
it('should generate key pair', () => {
|
|
661
|
+
const kp = basecoin.generateRootKeyPair();
|
|
662
|
+
basecoin.isValidPub(kp.pub).should.equal(true);
|
|
663
|
+
basecoin.isValidPrv(kp.prv).should.equal(true);
|
|
664
|
+
});
|
|
665
|
+
it('should generate key pair from seed', () => {
|
|
666
|
+
const seed = Buffer.from('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', 'hex');
|
|
667
|
+
const kp = basecoin.generateRootKeyPair(seed);
|
|
668
|
+
basecoin.isValidPub(kp.pub).should.equal(true);
|
|
669
|
+
kp.pub.should.equal('d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a');
|
|
670
|
+
basecoin.isValidPrv(kp.prv).should.equal(true);
|
|
671
|
+
kp.prv.should.equal('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a');
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
describe('Enable, disable and transfer Token ', () => {
|
|
675
|
+
it('should explain an enable token transaction hex', async function () {
|
|
676
|
+
const explain = await basecoin.explainTransaction({
|
|
677
|
+
txHex: AlgoResources.explainRawTx.enableToken,
|
|
678
|
+
feeInfo: { fee: '1000' },
|
|
679
|
+
});
|
|
680
|
+
explain.operations.length.should.equals(1);
|
|
681
|
+
explain.operations[0].type.should.equals('enableToken');
|
|
682
|
+
explain.operations[0].coin.should.equals('talgo:USON-16026728');
|
|
683
|
+
});
|
|
684
|
+
it('should explain an disable token transaction hex', async function () {
|
|
685
|
+
const explain = await basecoin.explainTransaction({
|
|
686
|
+
txHex: AlgoResources.explainRawTx.disableToken,
|
|
687
|
+
feeInfo: { fee: '1000' },
|
|
688
|
+
});
|
|
689
|
+
explain.operations.length.should.equals(1);
|
|
690
|
+
explain.operations[0].type.should.equals('disableToken');
|
|
691
|
+
explain.operations[0].coin.should.equals('talgo:USON-16026728');
|
|
692
|
+
});
|
|
693
|
+
it('should explain an transfer token transaction hex', async function () {
|
|
694
|
+
const explain = await basecoin.explainTransaction({
|
|
695
|
+
txHex: AlgoResources.explainRawTx.assetTransfer.signed,
|
|
696
|
+
feeInfo: { fee: '1000' },
|
|
697
|
+
});
|
|
698
|
+
explain.operations.length.should.equals(1);
|
|
699
|
+
explain.operations[0].type.should.equals('transferToken');
|
|
700
|
+
explain.operations[0].coin.should.equals('AlgoToken unknown');
|
|
701
|
+
});
|
|
702
|
+
it('should explain an enable USDT token transaction hex', async function () {
|
|
703
|
+
const explain = await basecoin.explainTransaction({
|
|
704
|
+
txHex: AlgoResources.explainRawTx.enableTokenUSDT,
|
|
705
|
+
feeInfo: { fee: '1000' },
|
|
706
|
+
});
|
|
707
|
+
explain.operations.length.should.equals(1);
|
|
708
|
+
explain.operations[0].type.should.equals('enableToken');
|
|
709
|
+
explain.operations[0].coin.should.equals('talgo:USDt-180447');
|
|
710
|
+
});
|
|
711
|
+
it('should explain an enable USDC token transaction hex', async function () {
|
|
712
|
+
const explain = await basecoin.explainTransaction({
|
|
713
|
+
txHex: AlgoResources.explainRawTx.enableTokenUSDC,
|
|
714
|
+
feeInfo: { fee: '1000' },
|
|
715
|
+
});
|
|
716
|
+
explain.operations.length.should.equals(1);
|
|
717
|
+
explain.operations[0].type.should.equals('enableToken');
|
|
718
|
+
explain.operations[0].coin.should.equals('talgo:USDC-10458941');
|
|
719
|
+
});
|
|
720
|
+
it('should explain an disable USDC token transaction hex', async function () {
|
|
721
|
+
const explain = await basecoin.explainTransaction({
|
|
722
|
+
txHex: AlgoResources.explainRawTx.disableTokenUSDC,
|
|
723
|
+
feeInfo: { fee: '1000' },
|
|
724
|
+
});
|
|
725
|
+
explain.operations.length.should.equals(1);
|
|
726
|
+
explain.operations[0].type.should.equals('disableToken');
|
|
727
|
+
explain.operations[0].coin.should.equals('talgo:USDC-10458941');
|
|
728
|
+
});
|
|
729
|
+
it('should explain an transfer USDC token transaction hex', async function () {
|
|
730
|
+
const explain = await basecoin.explainTransaction({
|
|
731
|
+
txHex: AlgoResources.explainRawTx.USDCAssetTransfer.signed,
|
|
732
|
+
feeInfo: { fee: '1000' },
|
|
733
|
+
});
|
|
734
|
+
explain.operations.length.should.equals(1);
|
|
735
|
+
explain.operations[0].type.should.equals('transferToken');
|
|
736
|
+
explain.operations[0].coin.should.equals('talgo:USDC-10458941');
|
|
737
|
+
});
|
|
738
|
+
});
|
|
739
|
+
describe('deriveKeyWithSeed', function () {
|
|
740
|
+
it('should derive key with seed', function () {
|
|
741
|
+
(() => {
|
|
742
|
+
basecoin.deriveKeyWithSeed('test');
|
|
743
|
+
}).should.throw('method deriveKeyWithSeed not supported for eddsa curve');
|
|
744
|
+
});
|
|
745
|
+
});
|
|
746
|
+
describe('Recovery', function () {
|
|
747
|
+
const fee = 1000;
|
|
748
|
+
const userKey = '{"iv":"ZJg0a0+zT+684MUl44Lm4A==","v":1,"iter":10000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"abQy0OL2468=","ct":"LNlSlTJED8jSwHCmUflzqFtRPL+PojzOgfd5mD2nmLVdAoyKCWHvAieKt7lJ7zg417CUi6Qj77/s3lbqmxVsfEsk"}';
|
|
749
|
+
const userPub = 'S4D7DDRAHWZIB2RCZICSRODFCNQXGANHGA7VCWBK5I37SQT6KVHXQNKMTE';
|
|
750
|
+
const backupKey = '{"iv":"mZY8XTvHxX8BPc1rdGQQww==","v":1,"iter":10000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"abQy0OL2468=","ct":"UQXo0EaPXb6TIZDYYhKYS9d/fRMNT6ptpl9BgJw3AVooSbO4nppWnTRYlQO7hpON4XY85hYDu/7hy91IX1z1bDDq"}';
|
|
751
|
+
const backupPub = '6FVGZUZOHZSXTTBRLWZDXGYSWVVYNN4ZESIEMZEMIBJCUBHC5C77OIE5RQ';
|
|
752
|
+
const rootAddress = 'FWLNDL7UXCSOPOQXA5VU2DMANZAYCCMBY377HKTGGMZ4GEPEJBFARDOGBA';
|
|
753
|
+
const walletPassphrase = 'Testing@43210!';
|
|
754
|
+
const recoveryDestination = 'GB3YETD5TSTBAIYGYHVWU3O3I7XGOB44HOZA5MOEF5M23CLLZKRQLEVAOA';
|
|
755
|
+
const bitgoPub = 'FJSWLLPRBXEGMWZY5BXA6673YKIK7JOURVCQEOWXC5TQPCXCOK3VHOO2VQ';
|
|
756
|
+
const nativeBalance = 10000000; // 10 ALGO
|
|
757
|
+
const MIN_ACCOUNT_BALANCE = 100000; // 1 AGLO
|
|
758
|
+
const nodeParams = {
|
|
759
|
+
token: '2810c2d168e8417c5f111d38d68327b8cfe2d0ddc02986490c22f8ddf4128bcd',
|
|
760
|
+
baseServer: 'http://localhost/',
|
|
761
|
+
port: 8443,
|
|
762
|
+
};
|
|
763
|
+
describe('Non-BitGo', async function () {
|
|
764
|
+
const sandBox = sinon_1.default.createSandbox();
|
|
765
|
+
const expectedAmount = new bignumber_js_1.default(nativeBalance).minus(fee).minus(MIN_ACCOUNT_BALANCE).toString();
|
|
766
|
+
afterEach(function () {
|
|
767
|
+
sandBox.verifyAndRestore();
|
|
768
|
+
});
|
|
769
|
+
it('should build and sign the recovery tx', async function () {
|
|
770
|
+
const getBalanceStub = sandBox.stub(algo_1.Algo.prototype, 'getAccountBalance').resolves(nativeBalance);
|
|
771
|
+
const recovery = await basecoin.recover({
|
|
772
|
+
userKey,
|
|
773
|
+
backupKey,
|
|
774
|
+
rootAddress,
|
|
775
|
+
walletPassphrase,
|
|
776
|
+
fee,
|
|
777
|
+
bitgoKey: bitgoPub,
|
|
778
|
+
recoveryDestination: recoveryDestination,
|
|
779
|
+
firstRound: 5002596,
|
|
780
|
+
nodeParams,
|
|
781
|
+
});
|
|
782
|
+
recovery.should.not.be.undefined();
|
|
783
|
+
recovery.should.have.property('id');
|
|
784
|
+
recovery.should.have.property('tx');
|
|
785
|
+
recovery.should.have.property('fee');
|
|
786
|
+
recovery.should.have.property('coin', 'talgo');
|
|
787
|
+
recovery.should.have.property('firstRound');
|
|
788
|
+
recovery.should.have.property('lastRound');
|
|
789
|
+
getBalanceStub.callCount.should.equal(1);
|
|
790
|
+
const factory = new src_1.AlgoLib.TransactionBuilderFactory(statics_1.coins.get('algo'));
|
|
791
|
+
const txBuilder = factory.from(recovery.tx);
|
|
792
|
+
const tx = await txBuilder.build();
|
|
793
|
+
const txBroadcastFormat = Buffer.from(tx.toBroadcastFormat()).toString('base64');
|
|
794
|
+
txBroadcastFormat.should.deepEqual(recovery.tx);
|
|
795
|
+
const txJson = tx.toJson();
|
|
796
|
+
txJson.amount.should.equal(expectedAmount);
|
|
797
|
+
txJson.to.should.equal(recoveryDestination);
|
|
798
|
+
txJson.from.should.equal(rootAddress);
|
|
799
|
+
txJson.fee.should.equal(fee);
|
|
800
|
+
});
|
|
801
|
+
it('should throw for invalid rootAddress', async function () {
|
|
802
|
+
const invalidRootAddress = 'randomstring';
|
|
803
|
+
await assert_1.default.rejects(async () => {
|
|
804
|
+
await basecoin.recover({
|
|
805
|
+
userKey,
|
|
806
|
+
backupKey,
|
|
807
|
+
rootAddress: invalidRootAddress,
|
|
808
|
+
walletPassphrase,
|
|
809
|
+
fee,
|
|
810
|
+
recoveryDestination: recoveryDestination,
|
|
811
|
+
firstRound: 5002596,
|
|
812
|
+
nodeParams,
|
|
813
|
+
});
|
|
814
|
+
}, { message: 'invalid rootAddress, got: ' + invalidRootAddress });
|
|
815
|
+
});
|
|
816
|
+
it('should throw for invalid recoveryDestination', async function () {
|
|
817
|
+
const invalidRecoveryDestination = 'randomstring';
|
|
818
|
+
await assert_1.default.rejects(async () => {
|
|
819
|
+
await basecoin.recover({
|
|
820
|
+
userKey,
|
|
821
|
+
backupKey,
|
|
822
|
+
rootAddress,
|
|
823
|
+
walletPassphrase,
|
|
824
|
+
fee,
|
|
825
|
+
recoveryDestination: invalidRecoveryDestination,
|
|
826
|
+
firstRound: 5002596,
|
|
827
|
+
nodeParams,
|
|
828
|
+
});
|
|
829
|
+
}, { message: 'invalid recoveryDestination, got: ' + invalidRecoveryDestination });
|
|
830
|
+
});
|
|
831
|
+
it('should throw if there is no enough balance to recover', async function () {
|
|
832
|
+
const getBalanceStub = sandBox.stub(algo_1.Algo.prototype, 'getAccountBalance').resolves(100500);
|
|
833
|
+
await assert_1.default.rejects(async () => {
|
|
834
|
+
await basecoin.recover({
|
|
835
|
+
userKey,
|
|
836
|
+
backupKey,
|
|
837
|
+
rootAddress,
|
|
838
|
+
fee,
|
|
839
|
+
walletPassphrase,
|
|
840
|
+
bitgoKey: bitgoPub,
|
|
841
|
+
recoveryDestination,
|
|
842
|
+
firstRound: 5003596,
|
|
843
|
+
nodeParams,
|
|
844
|
+
});
|
|
845
|
+
}, { message: 'Insufficient balance to recover, got balance: 100500 fee: 1000 min account balance: 100000' });
|
|
846
|
+
getBalanceStub.callCount.should.equal(1);
|
|
847
|
+
});
|
|
848
|
+
it('should throw if the walletPassphrase is undefined', async function () {
|
|
849
|
+
await assert_1.default.rejects(async () => {
|
|
850
|
+
await basecoin.recover({
|
|
851
|
+
userKey,
|
|
852
|
+
backupKey,
|
|
853
|
+
rootAddress,
|
|
854
|
+
fee,
|
|
855
|
+
recoveryDestination,
|
|
856
|
+
firstRound: 5003596,
|
|
857
|
+
nodeParams,
|
|
858
|
+
});
|
|
859
|
+
}, { message: 'walletPassphrase is required for non-bitgo recovery' });
|
|
860
|
+
});
|
|
861
|
+
it('should throw if the walletPassphrase is wrong', async function () {
|
|
862
|
+
await assert_1.default.rejects(async () => {
|
|
863
|
+
await basecoin.recover({
|
|
864
|
+
userKey,
|
|
865
|
+
backupKey,
|
|
866
|
+
rootAddress,
|
|
867
|
+
bitgoKey: bitgoPub,
|
|
868
|
+
walletPassphrase: 'wrongpassword',
|
|
869
|
+
fee,
|
|
870
|
+
recoveryDestination,
|
|
871
|
+
firstRound: 5003596,
|
|
872
|
+
nodeParams,
|
|
873
|
+
});
|
|
874
|
+
}, {
|
|
875
|
+
message: "unable to decrypt userKey or backupKey with the walletPassphrase provided, got error: password error - ccm: tag doesn't match",
|
|
876
|
+
});
|
|
877
|
+
});
|
|
878
|
+
it('should throw if bitgo key is not provided', async function () {
|
|
879
|
+
await assert_1.default.rejects(async () => {
|
|
880
|
+
await basecoin.recover({
|
|
881
|
+
userKey,
|
|
882
|
+
backupKey,
|
|
883
|
+
rootAddress,
|
|
884
|
+
walletPassphrase,
|
|
885
|
+
fee,
|
|
886
|
+
recoveryDestination,
|
|
887
|
+
firstRound: 5003596,
|
|
888
|
+
nodeParams,
|
|
889
|
+
});
|
|
890
|
+
}, {
|
|
891
|
+
message: 'bitgo public key from the keyCard is required for non-bitgo recovery',
|
|
892
|
+
});
|
|
893
|
+
});
|
|
894
|
+
it('should be able to pass a utf-8 encoded note', async function () {
|
|
895
|
+
const note = 'Non-BitGo Recovery Sweep Tx';
|
|
896
|
+
sandBox.stub(algo_1.Algo.prototype, 'getAccountBalance').resolves(nativeBalance);
|
|
897
|
+
const recovery = await basecoin.recover({
|
|
898
|
+
userKey,
|
|
899
|
+
backupKey,
|
|
900
|
+
rootAddress,
|
|
901
|
+
walletPassphrase,
|
|
902
|
+
fee,
|
|
903
|
+
bitgoKey: bitgoPub,
|
|
904
|
+
recoveryDestination: recoveryDestination,
|
|
905
|
+
firstRound: 5002596,
|
|
906
|
+
nodeParams,
|
|
907
|
+
note,
|
|
908
|
+
});
|
|
909
|
+
recovery.should.not.be.undefined();
|
|
910
|
+
recovery.note.should.be.equal(note);
|
|
911
|
+
});
|
|
912
|
+
});
|
|
913
|
+
describe('Unsigned Sweep', function () {
|
|
914
|
+
const sandBox = sinon_1.default.createSandbox();
|
|
915
|
+
const expectedAmount = new bignumber_js_1.default(nativeBalance).minus(fee).minus(MIN_ACCOUNT_BALANCE).toString();
|
|
916
|
+
let getBalanceStub;
|
|
917
|
+
beforeEach(function () {
|
|
918
|
+
getBalanceStub = sandBox.stub(algo_1.Algo.prototype, 'getAccountBalance').resolves(nativeBalance);
|
|
919
|
+
});
|
|
920
|
+
afterEach(function () {
|
|
921
|
+
sandBox.verifyAndRestore();
|
|
922
|
+
});
|
|
923
|
+
it('should build unsigned sweep tx', async function () {
|
|
924
|
+
const recovery = await basecoin.recover({
|
|
925
|
+
userKey: userPub,
|
|
926
|
+
backupKey: backupPub,
|
|
927
|
+
bitgoKey: bitgoPub,
|
|
928
|
+
rootAddress,
|
|
929
|
+
walletPassphrase,
|
|
930
|
+
fee,
|
|
931
|
+
recoveryDestination,
|
|
932
|
+
firstRound: 5003596,
|
|
933
|
+
nodeParams,
|
|
934
|
+
});
|
|
935
|
+
getBalanceStub.callCount.should.equal(1);
|
|
936
|
+
recovery.should.not.be.undefined();
|
|
937
|
+
recovery.should.have.property('txHex');
|
|
938
|
+
recovery.should.have.property('type');
|
|
939
|
+
recovery.should.have.property('amount');
|
|
940
|
+
recovery.should.have.property('feeInfo');
|
|
941
|
+
recovery.should.have.property('coin', 'talgo');
|
|
942
|
+
recovery.firstRound.should.not.be.undefined();
|
|
943
|
+
recovery.lastRound.should.not.be.undefined();
|
|
944
|
+
recovery.should.have.property('keys');
|
|
945
|
+
recovery.keys.should.deepEqual([userPub, backupPub, bitgoPub]);
|
|
946
|
+
recovery.addressVersion.should.equal(1);
|
|
947
|
+
getBalanceStub.callCount.should.equal(1);
|
|
948
|
+
const factory = new src_1.AlgoLib.TransactionBuilderFactory(statics_1.coins.get('algo'));
|
|
949
|
+
const txBuilder = factory.from(recovery.txHex);
|
|
950
|
+
const tx = await txBuilder.build();
|
|
951
|
+
Buffer.from(tx.toBroadcastFormat()).toString('hex').should.deepEqual(recovery.txHex);
|
|
952
|
+
const txJson = tx.toJson();
|
|
953
|
+
txJson.amount.should.equal(expectedAmount);
|
|
954
|
+
txJson.to.should.equal(recoveryDestination);
|
|
955
|
+
txJson.from.should.equal(rootAddress);
|
|
956
|
+
txJson.fee.should.equal(fee);
|
|
957
|
+
});
|
|
958
|
+
});
|
|
959
|
+
describe('Recovery with root keys', function () {
|
|
960
|
+
const sandBox = sinon_1.default.createSandbox();
|
|
961
|
+
let userKp;
|
|
962
|
+
let backupKp;
|
|
963
|
+
let rootAddress;
|
|
964
|
+
let encryptedUserPrv;
|
|
965
|
+
let encryptedBackupPrv;
|
|
966
|
+
const expectedAmount = new bignumber_js_1.default(nativeBalance).minus(fee).minus(MIN_ACCOUNT_BALANCE).toString();
|
|
967
|
+
let getBalanceStub;
|
|
968
|
+
beforeEach(function () {
|
|
969
|
+
const userSeed = Buffer.from('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', 'hex');
|
|
970
|
+
userKp = basecoin.generateRootKeyPair(userSeed);
|
|
971
|
+
encryptedUserPrv = bitgo.encrypt({
|
|
972
|
+
input: userKp.prv,
|
|
973
|
+
password: walletPassphrase,
|
|
974
|
+
});
|
|
975
|
+
(0, assert_1.default)(userKp.pub);
|
|
976
|
+
const backupSeed = Buffer.from('6d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', 'hex');
|
|
977
|
+
backupKp = basecoin.generateRootKeyPair(backupSeed);
|
|
978
|
+
encryptedBackupPrv = bitgo.encrypt({
|
|
979
|
+
input: backupKp.prv,
|
|
980
|
+
password: walletPassphrase,
|
|
981
|
+
});
|
|
982
|
+
const bitgoPub = 'FJSWLLPRBXEGMWZY5BXA6673YKIK7JOURVCQEOWXC5TQPCXCOK3VHOO2VQ';
|
|
983
|
+
const userAddress = src_1.AlgoLib.algoUtils.privateKeyToAlgoAddress(userKp.prv);
|
|
984
|
+
const backupAddress = src_1.AlgoLib.algoUtils.privateKeyToAlgoAddress(backupKp.prv);
|
|
985
|
+
rootAddress = src_1.AlgoLib.algoUtils.multisigAddress(1, 2, [userAddress, backupAddress, bitgoPub]);
|
|
986
|
+
});
|
|
987
|
+
afterEach(function () {
|
|
988
|
+
sandBox.verifyAndRestore();
|
|
989
|
+
});
|
|
990
|
+
it('should build and sign non-bitgo recovery tx with root keys', async function () {
|
|
991
|
+
getBalanceStub = sandBox.stub(algo_1.Algo.prototype, 'getAccountBalance').resolves(nativeBalance);
|
|
992
|
+
const recovery = await basecoin.recover({
|
|
993
|
+
userKey: encryptedUserPrv,
|
|
994
|
+
backupKey: encryptedBackupPrv,
|
|
995
|
+
rootAddress,
|
|
996
|
+
walletPassphrase,
|
|
997
|
+
fee,
|
|
998
|
+
bitgoKey: bitgoPub,
|
|
999
|
+
recoveryDestination: recoveryDestination,
|
|
1000
|
+
firstRound: 5002596,
|
|
1001
|
+
nodeParams,
|
|
1002
|
+
});
|
|
1003
|
+
recovery.should.not.be.undefined();
|
|
1004
|
+
recovery.should.have.property('id');
|
|
1005
|
+
recovery.should.have.property('tx');
|
|
1006
|
+
recovery.should.have.property('fee');
|
|
1007
|
+
recovery.should.have.property('coin', 'talgo');
|
|
1008
|
+
recovery.should.have.property('firstRound');
|
|
1009
|
+
recovery.should.have.property('lastRound');
|
|
1010
|
+
getBalanceStub.callCount.should.equal(1);
|
|
1011
|
+
const factory = new src_1.AlgoLib.TransactionBuilderFactory(statics_1.coins.get('algo'));
|
|
1012
|
+
const txBuilder = factory.from(recovery.tx);
|
|
1013
|
+
const tx = await txBuilder.build();
|
|
1014
|
+
const txBroadcastFormat = Buffer.from(tx.toBroadcastFormat()).toString('base64');
|
|
1015
|
+
txBroadcastFormat.should.deepEqual(recovery.tx);
|
|
1016
|
+
const txJson = tx.toJson();
|
|
1017
|
+
txJson.amount.should.equal(expectedAmount);
|
|
1018
|
+
txJson.to.should.equal(recoveryDestination);
|
|
1019
|
+
txJson.from.should.equal(rootAddress);
|
|
1020
|
+
txJson.fee.should.equal(fee);
|
|
1021
|
+
});
|
|
1022
|
+
it('should build unsigned sweep tx', async function () {
|
|
1023
|
+
getBalanceStub = sandBox.stub(algo_1.Algo.prototype, 'getAccountBalance').resolves(nativeBalance);
|
|
1024
|
+
const recovery = await basecoin.recover({
|
|
1025
|
+
userKey: userKp.pub,
|
|
1026
|
+
backupKey: backupKp.pub,
|
|
1027
|
+
bitgoKey: bitgoPub,
|
|
1028
|
+
rootAddress,
|
|
1029
|
+
walletPassphrase,
|
|
1030
|
+
fee,
|
|
1031
|
+
recoveryDestination,
|
|
1032
|
+
firstRound: 5003596,
|
|
1033
|
+
nodeParams,
|
|
1034
|
+
});
|
|
1035
|
+
getBalanceStub.callCount.should.equal(1);
|
|
1036
|
+
recovery.should.not.be.undefined();
|
|
1037
|
+
recovery.should.have.property('txHex');
|
|
1038
|
+
recovery.should.have.property('type');
|
|
1039
|
+
recovery.should.have.property('amount');
|
|
1040
|
+
recovery.should.have.property('feeInfo');
|
|
1041
|
+
recovery.should.have.property('coin', 'talgo');
|
|
1042
|
+
recovery.firstRound.should.not.be.undefined();
|
|
1043
|
+
recovery.lastRound.should.not.be.undefined();
|
|
1044
|
+
recovery.should.have.property('keys');
|
|
1045
|
+
recovery.keys.should.deepEqual([userKp.pub, backupKp.pub, bitgoPub]);
|
|
1046
|
+
recovery.addressVersion.should.equal(1);
|
|
1047
|
+
getBalanceStub.callCount.should.equal(1);
|
|
1048
|
+
const factory = new src_1.AlgoLib.TransactionBuilderFactory(statics_1.coins.get('algo'));
|
|
1049
|
+
const txBuilder = factory.from(recovery.txHex);
|
|
1050
|
+
const tx = await txBuilder.build();
|
|
1051
|
+
Buffer.from(tx.toBroadcastFormat()).toString('hex').should.deepEqual(recovery.txHex);
|
|
1052
|
+
const txJson = tx.toJson();
|
|
1053
|
+
txJson.amount.should.equal(expectedAmount);
|
|
1054
|
+
txJson.to.should.equal(recoveryDestination);
|
|
1055
|
+
txJson.from.should.equal(rootAddress);
|
|
1056
|
+
txJson.fee.should.equal(fee);
|
|
1057
|
+
});
|
|
1058
|
+
});
|
|
1059
|
+
});
|
|
1060
|
+
describe('AuditKey', () => {
|
|
1061
|
+
const { key } = algoBackupKey_1.algoBackupKey;
|
|
1062
|
+
const walletPassphrase = 'ZQ8MhxT84m4P';
|
|
1063
|
+
it('should return for valid inputs', () => {
|
|
1064
|
+
basecoin.assertIsValidKey({
|
|
1065
|
+
encryptedPrv: key,
|
|
1066
|
+
walletPassphrase,
|
|
1067
|
+
});
|
|
1068
|
+
});
|
|
1069
|
+
it('should throw error if the walletPassphrase is incorrect', () => {
|
|
1070
|
+
assert_1.default.throws(() => {
|
|
1071
|
+
basecoin.assertIsValidKey({
|
|
1072
|
+
encryptedPrv: key,
|
|
1073
|
+
walletPassphrase: 'foo',
|
|
1074
|
+
});
|
|
1075
|
+
}, { message: "failed to decrypt prv: ccm: tag doesn't match" });
|
|
1076
|
+
});
|
|
1077
|
+
it('should throw error if the key is altered', () => {
|
|
1078
|
+
const alteredKey = key.replace(/[0-9]/g, '0');
|
|
1079
|
+
assert_1.default.throws(() => {
|
|
1080
|
+
basecoin.assertIsValidKey({
|
|
1081
|
+
encryptedPrv: alteredKey,
|
|
1082
|
+
walletPassphrase,
|
|
1083
|
+
});
|
|
1084
|
+
}, { message: 'failed to decrypt prv: json decrypt: invalid parameters' });
|
|
1085
|
+
});
|
|
1086
|
+
it('should throw error if the key is not a valid key', () => {
|
|
1087
|
+
const invalidKey = '#@)$#($*@)#($*';
|
|
1088
|
+
const encryptedPrv = (0, sdk_api_1.encrypt)(walletPassphrase, invalidKey);
|
|
1089
|
+
assert_1.default.throws(() => {
|
|
1090
|
+
basecoin.assertIsValidKey({
|
|
1091
|
+
encryptedPrv,
|
|
1092
|
+
walletPassphrase,
|
|
1093
|
+
});
|
|
1094
|
+
}, { message: 'Invalid private key: Invalid base32 characters' });
|
|
1095
|
+
});
|
|
1096
|
+
});
|
|
1097
|
+
describe('blind signing token enablement protection', () => {
|
|
1098
|
+
let wallet;
|
|
1099
|
+
const bgUrl = sdk_core_1.common.Environments['mock'].uri;
|
|
1100
|
+
before(() => {
|
|
1101
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
|
|
1102
|
+
bitgo.safeRegister('talgo', src_1.Talgo.createInstance);
|
|
1103
|
+
bitgo.initializeTestVars();
|
|
1104
|
+
basecoin = bitgo.coin('talgo');
|
|
1105
|
+
wallet = new sdk_core_1.Wallet(bitgo, basecoin, {
|
|
1106
|
+
id: '123',
|
|
1107
|
+
coin: 'talgo',
|
|
1108
|
+
keys: ['1', '2', '3'],
|
|
1109
|
+
coinSpecific: {
|
|
1110
|
+
rootAddress: '123',
|
|
1111
|
+
},
|
|
1112
|
+
type: 'hot',
|
|
1113
|
+
});
|
|
1114
|
+
});
|
|
1115
|
+
it('should verify a valid token enablement transaction', async function () {
|
|
1116
|
+
const verifyTransactionStub = (0, sinon_1.spy)(basecoin, 'verifyTransaction');
|
|
1117
|
+
(0, nock_1.default)(bgUrl)
|
|
1118
|
+
.post(`/api/v2/talgo/wallet/${wallet.id()}/tx/build`)
|
|
1119
|
+
.reply(200, {
|
|
1120
|
+
txHex: 'iaRhcmN2xCBfnMgYtbyG4RL1DspYhxQeyn9QrJ+s2ZcDTcxK+yOH+KNmZWXNA+iiZnbOA2tlJKNnZW6sdGVzdG5ldC12MS4womdoxCBIY7UYpLPITsgQ8i1PEIHLD3HwWaesIN7GL39w5Qk6IqJsds4Da2kMo3NuZMQgX5zIGLW8huES9Q7KWIcUHsp/UKyfrNmXA03MSvsjh/ikdHlwZaVheGZlcqR4YWlkzgmpOkY=',
|
|
1121
|
+
txHash: 'ARYMOXMKZWM372JBFBTADZNJZU7S5HK44NZDZLVX5UR5UPIWT7FA',
|
|
1122
|
+
txInfo: {
|
|
1123
|
+
id: 'ARYMOXMKZWM372JBFBTADZNJZU7S5HK44NZDZLVX5UR5UPIWT7FA',
|
|
1124
|
+
type: 'axfer',
|
|
1125
|
+
from: 'L6OMQGFVXSDOCEXVB3FFRBYUD3FH6UFMT6WNTFYDJXGEV6ZDQ74EXGF6BE',
|
|
1126
|
+
fee: 1000,
|
|
1127
|
+
firstRound: 57369892,
|
|
1128
|
+
lastRound: 57370892,
|
|
1129
|
+
note: {},
|
|
1130
|
+
tokenId: 162085446,
|
|
1131
|
+
genesisID: 'testnet-v1.0',
|
|
1132
|
+
genesisHash: 'SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=',
|
|
1133
|
+
to: 'L6OMQGFVXSDOCEXVB3FFRBYUD3FH6UFMT6WNTFYDJXGEV6ZDQ74EXGF6BE',
|
|
1134
|
+
amount: '0',
|
|
1135
|
+
txType: 'enableToken',
|
|
1136
|
+
tokenName: 'TALGO',
|
|
1137
|
+
},
|
|
1138
|
+
feeInfo: {
|
|
1139
|
+
size: 251,
|
|
1140
|
+
fee: 1000,
|
|
1141
|
+
feeRate: 4,
|
|
1142
|
+
feeString: '1000',
|
|
1143
|
+
},
|
|
1144
|
+
keys: [
|
|
1145
|
+
'42MIYL2KBISV6WJRALTTSXHBEGLNF7MMQ74FGSYUCT5YP3V2KENJGRFVVQ',
|
|
1146
|
+
'MAGXZTDFW5QEXUKOUDIGHTXOKDW7TNQEDLWPBEZEL3VFU3YAA2PGYRS65M',
|
|
1147
|
+
'TMEJTI7XNCACDG3BTODINW6CMR6ARYIKTCFPA2GMIXL4X5Q4BCE6VHMWAM',
|
|
1148
|
+
],
|
|
1149
|
+
addressVersion: 1,
|
|
1150
|
+
coin: 'talgo',
|
|
1151
|
+
});
|
|
1152
|
+
const validatePwdStub = (0, sinon_1.stub)(wallet, 'getKeychainsAndValidatePassphrase').resolves([]);
|
|
1153
|
+
const signTxStub = (0, sinon_1.stub)(wallet, 'signTransaction').resolves({});
|
|
1154
|
+
await wallet.sendTokenEnablements({
|
|
1155
|
+
verification: { verifyTokenEnablement: true },
|
|
1156
|
+
enableTokens: [
|
|
1157
|
+
{
|
|
1158
|
+
name: 'talgo:JPT-162085446',
|
|
1159
|
+
address: 'L6OMQGFVXSDOCEXVB3FFRBYUD3FH6UFMT6WNTFYDJXGEV6ZDQ74EXGF6BE',
|
|
1160
|
+
},
|
|
1161
|
+
],
|
|
1162
|
+
});
|
|
1163
|
+
verifyTransactionStub.called.should.be.true();
|
|
1164
|
+
verifyTransactionStub.restore();
|
|
1165
|
+
validatePwdStub.restore();
|
|
1166
|
+
signTxStub.restore();
|
|
1167
|
+
});
|
|
1168
|
+
it('should throw error when invalid token enablement transaction is returned', async () => {
|
|
1169
|
+
const verifyTransactionStub = (0, sinon_1.spy)(basecoin, 'verifyTransaction');
|
|
1170
|
+
(0, nock_1.default)(bgUrl)
|
|
1171
|
+
.post(`/api/v2/talgo/wallet/${wallet.id()}/tx/build`)
|
|
1172
|
+
.reply(200, {
|
|
1173
|
+
txHex: 'iaRhcmN2xCBfnMgYtbyG4RL1DspYhxQeyn9QrJ+s2ZcDTcxK+yOH+KNmZWXNA+iiZnbOA2tpeqNnZW6sdGVzdG5ldC12MS4womdoxCBIY7UYpLPITsgQ8i1PEIHLD3HwWaesIN7GL39w5Qk6IqJsds4Da21io3NuZMQgX5zIGLW8huES9Q7KWIcUHsp/UKyfrNmXA03MSvsjh/ikdHlwZaVheGZlcqR4YWlkzgACwN8=',
|
|
1174
|
+
txHash: 'YPQGYNBOCPXMBFTBZH2AQGCDZ3C2762T6EYQY46F7LRG2URX6DLA',
|
|
1175
|
+
txInfo: {
|
|
1176
|
+
id: 'YPQGYNBOCPXMBFTBZH2AQGCDZ3C2762T6EYQY46F7LRG2URX6DLA',
|
|
1177
|
+
type: 'axfer',
|
|
1178
|
+
from: 'L6OMQGFVXSDOCEXVB3FFRBYUD3FH6UFMT6WNTFYDJXGEV6ZDQ74EXGF6BE',
|
|
1179
|
+
fee: 1000,
|
|
1180
|
+
firstRound: 57371002,
|
|
1181
|
+
lastRound: 57372002,
|
|
1182
|
+
note: {},
|
|
1183
|
+
tokenId: 180447,
|
|
1184
|
+
genesisID: 'testnet-v1.0',
|
|
1185
|
+
genesisHash: 'SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=',
|
|
1186
|
+
to: 'L6OMQGFVXSDOCEXVB3FFRBYUD3FH6UFMT6WNTFYDJXGEV6ZDQ74EXGF6BE',
|
|
1187
|
+
amount: '0',
|
|
1188
|
+
txType: 'enableToken',
|
|
1189
|
+
tokenName: 'TALGO',
|
|
1190
|
+
},
|
|
1191
|
+
feeInfo: {
|
|
1192
|
+
size: 251,
|
|
1193
|
+
fee: 1000,
|
|
1194
|
+
feeRate: 4,
|
|
1195
|
+
feeString: '1000',
|
|
1196
|
+
},
|
|
1197
|
+
keys: [
|
|
1198
|
+
'42MIYL2KBISV6WJRALTTSXHBEGLNF7MMQ74FGSYUCT5YP3V2KENJGRFVVQ',
|
|
1199
|
+
'MAGXZTDFW5QEXUKOUDIGHTXOKDW7TNQEDLWPBEZEL3VFU3YAA2PGYRS65M',
|
|
1200
|
+
'TMEJTI7XNCACDG3BTODINW6CMR6ARYIKTCFPA2GMIXL4X5Q4BCE6VHMWAM',
|
|
1201
|
+
],
|
|
1202
|
+
addressVersion: 1,
|
|
1203
|
+
coin: 'talgo',
|
|
1204
|
+
});
|
|
1205
|
+
(0, sinon_1.stub)(wallet, 'getKeychainsAndValidatePassphrase').resolves([]);
|
|
1206
|
+
(0, sinon_1.stub)(wallet, 'signTransaction').resolves({});
|
|
1207
|
+
const { success, failure } = await wallet.sendTokenEnablements({
|
|
1208
|
+
verification: { verifyTokenEnablement: true },
|
|
1209
|
+
enableTokens: [
|
|
1210
|
+
{
|
|
1211
|
+
name: 'talgo:JPT-162085446',
|
|
1212
|
+
address: 'L6OMQGFVXSDOCEXVB3FFRBYUD3FH6UFMT6WNTFYDJXGEV6ZDQ74EXGF6BE',
|
|
1213
|
+
},
|
|
1214
|
+
],
|
|
1215
|
+
});
|
|
1216
|
+
verifyTransactionStub.called.should.be.true();
|
|
1217
|
+
success.length.should.equal(0);
|
|
1218
|
+
failure.length.should.equal(1);
|
|
1219
|
+
failure[0].message.should.equal('Token enablement verification failed: expected token ID 162085446 but transaction has token ID 180447');
|
|
1220
|
+
});
|
|
1221
|
+
});
|
|
1222
|
+
});
|
|
1223
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxnby5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC9hbGdvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsbUNBQTJDO0FBQzNDLG1EQUErRDtBQUMvRCxpREFBd0Q7QUFDeEQsZ0VBQWtEO0FBQ2xELG1DQUFxQztBQUNyQyxpREFBNEM7QUFDNUMsK0NBQW9EO0FBQ3BELG9EQUE0QjtBQUM1Qix5Q0FBc0M7QUFDdEMsZ0VBQXFDO0FBQ3JDLHVDQUEwRDtBQUMxRCxtREFBK0Q7QUFDL0QsNERBQXlEO0FBQ3pELGdEQUF3QjtBQUV4QixRQUFRLENBQUMsT0FBTyxFQUFFO0lBQ2hCLElBQUksS0FBbUIsQ0FBQztJQUN4QixJQUFJLFFBQVEsQ0FBQztJQUNiLE1BQU0sUUFBUSxHQUFHLGFBQWEsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDO0lBRWpELE1BQU0sQ0FBQztRQUNMLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDdEQsS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsV0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ2xELEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzNCLFFBQVEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pDLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGVBQWUsRUFBRSxHQUFHLEVBQUU7UUFDN0IsRUFBRSxDQUFDLHVCQUF1QixFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ3JDLE1BQU0sUUFBUTtpQkFDWCxrQkFBa0IsQ0FBQztnQkFDbEIsTUFBTSxFQUFFLEVBQUU7YUFDWCxDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLCtCQUErQixD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dUcsQ0FDeEcsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFsZ29MaWIsIFRhbGdvIH0gZnJvbSAnLi4vLi4vc3JjJztcbmltcG9ydCB7IFRlc3RCaXRHbywgVGVzdEJpdEdvQVBJIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLXRlc3QnO1xuaW1wb3J0IHsgQml0R29BUEksIGVuY3J5cHQgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstYXBpJztcbmltcG9ydCAqIGFzIEFsZ29SZXNvdXJjZXMgZnJvbSAnLi4vZml4dHVyZXMvYWxnbyc7XG5pbXBvcnQgeyByYW5kb21CeXRlcyB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBjb2lucyB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IFNpbm9uLCB7IFNpbm9uU3R1Yiwgc3B5LCBzdHViIH0gZnJvbSAnc2lub24nO1xuaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgQWxnbyB9IGZyb20gJy4uLy4uL3NyYy9hbGdvJztcbmltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkgfSBmcm9tICcuLi8uLi9zcmMvbGliJztcbmltcG9ydCB7IGNvbW1vbiwgS2V5UGFpciwgV2FsbGV0IH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgYWxnb0JhY2t1cEtleSB9IGZyb20gJy4vZml4dHVyZXMvYWxnb0JhY2t1cEtleSc7XG5pbXBvcnQgbm9jayBmcm9tICdub2NrJztcblxuZGVzY3JpYmUoJ0FMR086JywgZnVuY3Rpb24gKCkge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGJhc2Vjb2luO1xuICBjb25zdCByZWNlaXZlciA9IEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDI7XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBiaXRnby5zYWZlUmVnaXN0ZXIoJ3RhbGdvJywgVGFsZ28uY3JlYXRlSW5zdGFuY2UpO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIGJhc2Vjb2luID0gYml0Z28uY29pbigndGFsZ28nKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1Nob3VsZCBGYWlsOiAnLCAoKSA9PiB7XG4gICAgaXQoJ0RvZXMgbm90IGhhdmUgYSB0eEhleCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHBhcmFtczoge30sXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIGV4cGxhaW4gdHggcGFyYW1ldGVycycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ0RvZXMgbm90IGhhdmUgYSBmZWUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAuZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgICBwYXJhbXM6IHtcbiAgICAgICAgICAgIHR4SGV4OiAnU29tZSBWYWxpZCBIZXgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIGV4cGxhaW4gdHggcGFyYW1ldGVycycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVHJhbnNmZXIgQnVpbGRlcjogJywgKCkgPT4ge1xuICAgIGNvbnN0IGJ1aWxkQmFzZVRyYW5zZmVyVHJhbnNhY3Rpb24gPSAoeyBkZXN0aW5hdGlvbiwgYW1vdW50ID0gMTAwMDAsIHNlbmRlciwgbWVtbyA9ICcnIH0pID0+IHtcbiAgICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgQWxnb0xpYi5UcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW5zLmdldCgnYWxnbycpKTtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBjb25zdCBsZWFzZSA9IG5ldyBVaW50OEFycmF5KHJhbmRvbUJ5dGVzKDMyKSk7XG4gICAgICBjb25zdCBub3RlID0gbmV3IFVpbnQ4QXJyYXkoQnVmZmVyLmZyb20obWVtbywgJ3V0Zi04JykpO1xuICAgICAgdHhCdWlsZGVyXG4gICAgICAgIC5zZW5kZXIoeyBhZGRyZXNzOiBzZW5kZXIgfSlcbiAgICAgICAgLnRvKHsgYWRkcmVzczogZGVzdGluYXRpb24gfSlcbiAgICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAgIC5pc0ZsYXRGZWUodHJ1ZSlcbiAgICAgICAgLmZlZSh7XG4gICAgICAgICAgZmVlOiAnMTAwMCcsXG4gICAgICAgIH0pXG4gICAgICAgIC5maXJzdFJvdW5kKDEpXG4gICAgICAgIC5sYXN0Um91bmQoMTAwKVxuICAgICAgICAubGVhc2UobGVhc2UpXG4gICAgICAgIC5ub3RlKG5vdGUpXG4gICAgICAgIC50ZXN0bmV0KCk7XG4gICAgICByZXR1cm4gdHhCdWlsZGVyO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBCdWlsZCBhbiB1bnNpZ25lZCBhY2NvdW50LWxpYiBzaW5nbGUtc2lnbmF0dXJlIHNlbmQgdHJhbnNhY3Rpb25cbiAgICAgKiBAcGFyYW0gc2VuZGVyIFRoZSBzZW5kZXJzIGFkZHJlc3NcbiAgICAgKiBAcGFyYW0gZGVzdGluYXRpb24gVGhlIGRlc3RpbmF0aW9uIGFkZHJlc3Mgb2YgdGhlIHRyYW5zYWN0aW9uXG4gICAgICogQHBhcmFtIGFtb3VudCBUaGUgYW1vdW50IHRvIHNlbmQgdG8gdGhlIHJlY2lwaWVudFxuICAgICAqIEBwYXJhbSBtZW1vIE9wdGlvbmFsIG5vdGUgd2l0aCB0aGUgdHJhbnNhY3Rpb25cbiAgICAgKi9cbiAgICBjb25zdCBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24gPSBhc3luYyBmdW5jdGlvbiAoeyBzZW5kZXIsIGRlc3RpbmF0aW9uLCBhbW91bnQgPSAxMDAwMCwgbWVtbyA9ICcnIH0pIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGJ1aWxkQmFzZVRyYW5zZmVyVHJhbnNhY3Rpb24oeyBzZW5kZXIsIGRlc3RpbmF0aW9uLCBhbW91bnQsIG1lbW8gfSk7XG4gICAgICByZXR1cm4gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEJ1aWxkIGEgc2lnbmVkIGFjY291bnQtbGliIHNpbmdsZS1zaWduYXR1cmUgc2VuZCB0cmFuc2FjdGlvblxuICAgICAqIEBwYXJhbSBzZW5kZXIgVGhlIHNlbmRlcnMgYWRkcmVzc1xuICAgICAqIEBwYXJhbSBkZXN0aW5hdGlvbiBUaGUgZGVzdGluYXRpb24gYWRkcmVzcyBvZiB0aGUgdHJhbnNhY3Rpb25cbiAgICAgKiBAcGFyYW0gYW1vdW50IFRoZSBhbW91bnQgdG8gc2VuZCB0byB0aGUgcmVjaXBpZW50XG4gICAgICogQHBhcmFtIG1lbW8gT3B0aW9uYWwgbm90ZSB3aXRoIHRoZSB0cmFuc2FjdGlvblxuICAgICAqL1xuICAgIGNvbnN0IGJ1aWxkU2lnbmVkVHJhbnNhY3Rpb24gPSBhc3luYyBmdW5jdGlvbiAoeyBzZW5kZXIsIGRlc3RpbmF0aW9uLCBhbW91bnQgPSAxMDAwMCwgbWVtbyA9ICcnIH0pIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGJ1aWxkQmFzZVRyYW5zZmVyVHJhbnNhY3Rpb24oeyBzZW5kZXIsIGRlc3RpbmF0aW9uLCBhbW91bnQsIG1lbW8gfSk7XG4gICAgICB0eEJ1aWxkZXIubnVtYmVyT2ZTaWduZXJzKDEpO1xuICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDEucHJ2S2V5IH0pO1xuICAgICAgcmV0dXJuIGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBCdWlsZCBhIG11bHRpLXNpZ25lZCBhY2NvdW50LWxpYiBzaW5nbGUtc2lnbmF0dXJlIHNlbmQgdHJhbnNhY3Rpb25cbiAgICAgKiBAcGFyYW0gc2VuZGVycyBUaGUgbGlzdCBvZiBzZW5kZXJzXG4gICAgICogQHBhcmFtIGRlc3RpbmF0aW9uIFRoZSBkZXN0aW5hdGlvbiBhZGRyZXNzIG9mIHRoZSB0cmFuc2FjdGlvblxuICAgICAqIEBwYXJhbSBhbW91bnQgVGhlIGFtb3VudCB0byBzZW5kIHRvIHRoZSByZWNpcGllbnRcbiAgICAgKiBAcGFyYW0gbWVtbyBPcHRpb25hbCBub3RlIHdpdGggdGhlIHRyYW5zYWN0aW9uXG4gICAgICovXG4gICAgY29uc3QgYnVpbGRNdWx0aVNpZ25lZFRyYW5zYWN0aW9uID0gYXN5bmMgZnVuY3Rpb24gKHsgc2VuZGVycywgZGVzdGluYXRpb24sIGFtb3VudCA9IDEwMDAwLCBtZW1vID0gJycgfSkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gYnVpbGRCYXNlVHJhbnNmZXJUcmFuc2FjdGlvbih7IHNlbmRlcjogc2VuZGVyc1swXSwgZGVzdGluYXRpb24sIGFtb3VudCwgbWVtbyB9KTtcbiAgICAgIHR4QnVpbGRlci5udW1iZXJPZlNpZ25lcnMoMik7XG4gICAgICB0eEJ1aWxkZXIuc2V0U2lnbmVycyhzZW5kZXJzKTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQxLnBydktleSB9KTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQzLnBydktleSB9KTtcbiAgICAgIHJldHVybiBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICB9O1xuXG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGFuIHVuc2lnbmVkIHRyYW5zZmVyIHRyYW5zYWN0aW9uIGhleCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgudHJhbnNmZXIudW5zaWduZWQsXG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAnMTAwMCcgfSxcbiAgICAgIH0pO1xuICAgICAgZXhwbGFpbi5vdXRwdXRBbW91bnQuc2hvdWxkLmVxdWFsKCcxMDAwMCcpO1xuICAgICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoJzEwMDAwJyk7XG4gICAgICBleHBsYWluLm91dHB1dHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwocmVjZWl2ZXIuYWRkcmVzcyk7XG4gICAgICBCdWZmZXIuZnJvbShleHBsYWluLm91dHB1dHNbMF0ubWVtbykudG9TdHJpbmcoKS5zaG91bGQuZXF1YWwoQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgudHJhbnNmZXIubm90ZSk7XG4gICAgICBleHBsYWluLmZlZS5zaG91bGQuZXF1YWwoMTAwMCk7XG4gICAgICBleHBsYWluLmNoYW5nZUFtb3VudC5zaG91bGQuZXF1YWwoJzAnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhIHNpZ25lZCB0cmFuc2ZlciB0cmFuc2FjdGlvbiBoZXgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBsYWluID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhIZXg6IEFsZ29SZXNvdXJjZXMuZXhwbGFpblJhd1R4LnRyYW5zZmVyLnNpZ25lZCxcbiAgICAgICAgZmVlSW5mbzogeyBmZWU6ICcxMDAwJyB9LFxuICAgICAgfSk7XG4gICAgICBleHBsYWluLm91dHB1dEFtb3VudC5zaG91bGQuZXF1YWwoJzEwMDAwJyk7XG4gICAgICBleHBsYWluLm91dHB1dHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbCgnMTAwMDAnKTtcbiAgICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbChyZWNlaXZlci5hZGRyZXNzKTtcbiAgICAgIEJ1ZmZlci5mcm9tKGV4cGxhaW4ub3V0cHV0c1swXS5tZW1vKS50b1N0cmluZygpLnNob3VsZC5lcXVhbChBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC50cmFuc2Zlci5ub3RlKTtcbiAgICAgIGV4cGxhaW4uZmVlLnNob3VsZC5lcXVhbCgxMDAwKTtcbiAgICAgIGV4cGxhaW4uY2hhbmdlQW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGEgbXVsdGlTaWcgdHJhbnNmZXIgdHJhbnNhY3Rpb24gaGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4SGV4OiBBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC50cmFuc2Zlci5tdWx0aVNpZ25lZCxcbiAgICAgICAgZmVlSW5mbzogeyBmZWU6ICcxMDAwJyB9LFxuICAgICAgfSk7XG4gICAgICBleHBsYWluLm91dHB1dEFtb3VudC5zaG91bGQuZXF1YWwoJzEwMDAwJyk7XG4gICAgICBleHBsYWluLm91dHB1dHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbCgnMTAwMDAnKTtcbiAgICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbChyZWNlaXZlci5hZGRyZXNzKTtcbiAgICAgIEJ1ZmZlci5mcm9tKGV4cGxhaW4ub3V0cHV0c1swXS5tZW1vKS50b1N0cmluZygpLnNob3VsZC5lcXVhbChBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC50cmFuc2Zlci5ub3RlKTtcbiAgICAgIGV4cGxhaW4uZmVlLnNob3VsZC5lcXVhbCgxMDAwKTtcbiAgICAgIGV4cGxhaW4uY2hhbmdlQW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGEgaGFsZiBzaWduZWQgdHJhbnNmZXIgdHJhbnNhY3Rpb24gaGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgIGhhbGZTaWduZWQ6IHtcbiAgICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgudHJhbnNmZXIuaGFsZlNpZ25lZCxcbiAgICAgICAgfSxcbiAgICAgICAgZmVlSW5mbzogeyBmZWU6ICcxMDAwJyB9LFxuICAgICAgfSk7XG4gICAgICBleHBsYWluLm91dHB1dEFtb3VudC5zaG91bGQuZXF1YWwoJzEwMDAwJyk7XG4gICAgICBleHBsYWluLm91dHB1dHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbCgnMTAwMDAnKTtcbiAgICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbChyZWNlaXZlci5hZGRyZXNzKTtcbiAgICAgIEJ1ZmZlci5mcm9tKGV4cGxhaW4ub3V0cHV0c1swXS5tZW1vKS50b1N0cmluZygpLnNob3VsZC5lcXVhbChBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC50cmFuc2Zlci5ub3RlKTtcbiAgICAgIGV4cGxhaW4uZmVlLnNob3VsZC5lcXVhbCgxMDAwKTtcbiAgICAgIGV4cGxhaW4uY2hhbmdlQW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGFuIHVuc2lnbmVkIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2VuZGVyID0gQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50MS5hZGRyZXNzO1xuICAgICAgY29uc3QgZGVzdGluYXRpb24gPSBBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQyLmFkZHJlc3M7XG4gICAgICBjb25zdCBhbW91bnQgPSAxMDAwMDtcbiAgICAgIGNvbnN0IG1lbW8gPSBBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC50cmFuc2Zlci5ub3RlO1xuICAgICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJ1aWxkVW5zaWduZWRUcmFuc2FjdGlvbih7XG4gICAgICAgIHNlbmRlcixcbiAgICAgICAgZGVzdGluYXRpb24sXG4gICAgICAgIGFtb3VudCxcbiAgICAgICAgbWVtbyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdW5zaWduZWRIZXggPSBCdWZmZXIuZnJvbSh1bnNpZ25lZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCkpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogdW5zaWduZWRIZXgsXG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAnMTAwMCcgfSxcbiAgICAgIH0pO1xuICAgICAgQnVmZmVyLmZyb20oZXhwbGFpbi5vdXRwdXRzWzBdLm1lbW8pLnRvU3RyaW5nKCkuc2hvdWxkLmVxdWFsKEFsZ29SZXNvdXJjZXMuZXhwbGFpblJhd1R4LnRyYW5zZmVyLm5vdGUpO1xuICAgICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoYW1vdW50LnRvU3RyaW5nKCkpO1xuICAgICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKGRlc3RpbmF0aW9uKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhIHNpZ25lZCB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNlbmRlciA9IEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcztcbiAgICAgIGNvbnN0IGRlc3RpbmF0aW9uID0gQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50Mi5hZGRyZXNzO1xuICAgICAgY29uc3QgYW1vdW50ID0gMTAwMDA7XG4gICAgICBjb25zdCBtZW1vID0gQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgudHJhbnNmZXIubm90ZTtcbiAgICAgIGNvbnN0IHNpZ25lZFRyYW5zYWN0aW9uID0gYXdhaXQgYnVpbGRTaWduZWRUcmFuc2FjdGlvbih7XG4gICAgICAgIHNlbmRlcixcbiAgICAgICAgZGVzdGluYXRpb24sXG4gICAgICAgIGFtb3VudCxcbiAgICAgICAgbWVtbyxcbiAgICAgIH0pO1xuICAgICAgY29uc3Qgc2lnbmVkSGV4ID0gQnVmZmVyLmZyb20oc2lnbmVkVHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4SGV4OiBzaWduZWRIZXgsXG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAnMTAwMCcgfSxcbiAgICAgIH0pO1xuICAgICAgQnVmZmVyLmZyb20oZXhwbGFpbi5vdXRwdXRzWzBdLm1lbW8pLnRvU3RyaW5nKCkuc2hvdWxkLmVxdWFsKEFsZ29SZXNvdXJjZXMuZXhwbGFpblJhd1R4LnRyYW5zZmVyLm5vdGUpO1xuICAgICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoYW1vdW50LnRvU3RyaW5nKCkpO1xuICAgICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKGRlc3RpbmF0aW9uKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhIG11bHRpU2lnbmVkIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2VuZGVycyA9IFtBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQxLmFkZHJlc3MsIEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDMuYWRkcmVzc107XG4gICAgICBjb25zdCBkZXN0aW5hdGlvbiA9IEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDIuYWRkcmVzcztcbiAgICAgIGNvbnN0IGFtb3VudCA9IDEwMDAwO1xuICAgICAgY29uc3QgbWVtbyA9IEFsZ29SZXNvdXJjZXMuZXhwbGFpblJhd1R4LnRyYW5zZmVyLm5vdGU7XG4gICAgICBjb25zdCBzaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJ1aWxkTXVsdGlTaWduZWRUcmFuc2FjdGlvbih7XG4gICAgICAgIHNlbmRlcnMsXG4gICAgICAgIGRlc3RpbmF0aW9uLFxuICAgICAgICBhbW91bnQsXG4gICAgICAgIG1lbW8sXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHNpZ25lZEhleCA9IEJ1ZmZlci5mcm9tKHNpZ25lZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCkpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogc2lnbmVkSGV4LFxuICAgICAgICBmZWVJbmZvOiB7IGZlZTogJzEwMDAnIH0sXG4gICAgICB9KTtcbiAgICAgIEJ1ZmZlci5mcm9tKGV4cGxhaW4ub3V0cHV0c1swXS5tZW1vKS50b1N0cmluZygpLnNob3VsZC5lcXVhbChBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC50cmFuc2Zlci5ub3RlKTtcbiAgICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKGFtb3VudC50b1N0cmluZygpKTtcbiAgICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbChkZXN0aW5hdGlvbik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdBc3NldCBUcmFuc2ZlciBCdWlsZGVyOiAnLCAoKSA9PiB7XG4gICAgY29uc3QgYnVpbGRCYXNlQXNzZXRUcmFuc2ZlclRyYW5zYWN0aW9uID0gKHsgZGVzdGluYXRpb24sIGFtb3VudCA9IDEwMDAsIHRva2VuSWQsIHNlbmRlciB9KSA9PiB7XG4gICAgICBjb25zdCBmYWN0b3J5ID0gbmV3IEFsZ29MaWIuVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2lucy5nZXQoJ2FsZ28nKSk7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldEFzc2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBjb25zdCBsZWFzZSA9IG5ldyBVaW50OEFycmF5KHJhbmRvbUJ5dGVzKDMyKSk7XG4gICAgICB0eEJ1aWxkZXJcbiAgICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IHNlbmRlciB9KVxuICAgICAgICAuaXNGbGF0RmVlKHRydWUpXG4gICAgICAgIC5mZWUoe1xuICAgICAgICAgIGZlZTogJzEwMDAnLFxuICAgICAgICB9KVxuICAgICAgICAudG9rZW5JZCh0b2tlbklkKVxuICAgICAgICAuZmlyc3RSb3VuZCgxKVxuICAgICAgICAubGFzdFJvdW5kKDEwMClcbiAgICAgICAgLmxlYXNlKGxlYXNlKVxuICAgICAgICAudG8oeyBhZGRyZXNzOiBkZXN0aW5hdGlvbiB9KVxuICAgICAgICAuYW1vdW50KGFtb3VudClcbiAgICAgICAgLnRlc3RuZXQoKTtcbiAgICAgIHJldHVybiB0eEJ1aWxkZXI7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEJ1aWxkIGFuIHVuc2lnbmVkIGFjY291bnQtbGliIHNpbmdsZS1zaWduYXR1cmUgYXNzZXQgdHJhbnNmZXIgdHJhbnNhY3Rpb25cbiAgICAgKiBAcGFyYW0gc2VuZGVyIFRoZSBzZW5kZXJzIGFkZHJlc3NcbiAgICAgKiBAcGFyYW0gZGVzdGluYXRpb24gVGhlIGRlc3RpbmF0aW9uIGFkZHJlc3Mgb2YgdGhlIHRyYW5zYWN0aW9uXG4gICAgICogQHBhcmFtIGFtb3VudCBUaGUgYW1vdW50IHRvIHNlbmQgdG8gdGhlIHJlY2lwaWVudFxuICAgICAqIEBwYXJhbSB0b2tlbklkIFRoZSBhc3NldEluZGV4IGZvciB0aGUgdG9rZW5cbiAgICAgKi9cbiAgICBjb25zdCBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24gPSBhc3luYyBmdW5jdGlvbiAoeyBzZW5kZXIsIGRlc3RpbmF0aW9uLCBhbW91bnQgPSAxMDAwMCwgdG9rZW5JZCB9KSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBidWlsZEJhc2VBc3NldFRyYW5zZmVyVHJhbnNhY3Rpb24oeyBzZW5kZXIsIGRlc3RpbmF0aW9uLCBhbW91bnQsIHRva2VuSWQgfSk7XG4gICAgICByZXR1cm4gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEJ1aWxkIGEgc2lnbmVkIGFjY291bnQtbGliIHNpbmdsZS1zaWduYXR1cmUgc2VuZCB0cmFuc2FjdGlvblxuICAgICAqIEBwYXJhbSBzZW5kZXIgVGhlIHNlbmRlcnMgYWRkcmVzc1xuICAgICAqIEBwYXJhbSBkZXN0aW5hdGlvbiBUaGUgZGVzdGluYXRpb24gYWRkcmVzcyBvZiB0aGUgdHJhbnNhY3Rpb25cbiAgICAgKiBAcGFyYW0gYW1vdW50IFRoZSBhbW91bnQgdG8gc2VuZCB0byB0aGUgcmVjaXBpZW50XG4gICAgICogQHBhcmFtIHRva2VuSWQgVGhlIGFzc2V0SW5kZXggZm9yIHRoZSB0b2tlblxuICAgICAqL1xuICAgIGNvbnN0IGJ1aWxkU2lnbmVkVHJhbnNhY3Rpb24gPSBhc3luYyBmdW5jdGlvbiAoeyBzZW5kZXIsIGRlc3RpbmF0aW9uLCBhbW91bnQgPSAxMDAwMCwgdG9rZW5JZCB9KSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBidWlsZEJhc2VBc3NldFRyYW5zZmVyVHJhbnNhY3Rpb24oeyBzZW5kZXIsIGRlc3RpbmF0aW9uLCBhbW91bnQsIHRva2VuSWQgfSk7XG4gICAgICB0eEJ1aWxkZXIubnVtYmVyT2ZTaWduZXJzKDEpO1xuICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDEucHJ2S2V5IH0pO1xuICAgICAgcmV0dXJuIGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgIH07XG5cbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gYW4gdW5zaWduZWQgYXNzZXQgdHJhbnNmZXIgdHJhbnNhY3Rpb24gaGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4SGV4OiBBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC5hc3NldFRyYW5zZmVyLnVuc2lnbmVkLFxuICAgICAgICBmZWVJbmZvOiB7IGZlZTogJzEwMDAnIH0sXG4gICAgICB9KTtcbiAgICAgIGV4cGxhaW4ub3V0cHV0QW1vdW50LnNob3VsZC5lcXVhbCgnMTAwMCcpO1xuICAgICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoJzEwMDAnKTtcbiAgICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbChyZWNlaXZlci5hZGRyZXNzKTtcbiAgICAgIGV4cGxhaW4uZmVlLnNob3VsZC5lcXVhbCgxMDAwKTtcbiAgICAgIGV4cGxhaW4uY2hhbmdlQW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICAgICAgZXhwbGFpbi50b2tlbklkLnNob3VsZC5lcXVhbCgxKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhIHNpZ25lZCBhc3NldCB0cmFuc2ZlciB0cmFuc2FjdGlvbiBoZXgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBsYWluID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhIZXg6IEFsZ29SZXNvdXJjZXMuZXhwbGFpblJhd1R4LmFzc2V0VHJhbnNmZXIuc2lnbmVkLFxuICAgICAgICBmZWVJbmZvOiB7IGZlZTogJzEwMDAnIH0sXG4gICAgICB9KTtcbiAgICAgIGV4cGxhaW4ub3V0cHV0QW1vdW50LnNob3VsZC5lcXVhbCgnMTAwMDAwMDAwMDAwMDAwMDAwMDAnKTtcbiAgICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKCcxMDAwMDAwMDAwMDAwMDAwMDAwMCcpO1xuICAgICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKHJlY2VpdmVyLmFkZHJlc3MpO1xuICAgICAgZXhwbGFpbi5mZWUuc2hvdWxkLmVxdWFsKDEwMDApO1xuICAgICAgZXhwbGFpbi5jaGFuZ2VBbW91bnQuc2hvdWxkLmVxdWFsKCcwJyk7XG4gICAgICBleHBsYWluLnRva2VuSWQuc2hvdWxkLmVxdWFsKDEpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGFuIHVuc2lnbmVkIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2VuZGVyID0gQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50MS5hZGRyZXNzO1xuICAgICAgY29uc3QgZGVzdGluYXRpb24gPSBBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQyLmFkZHJlc3M7XG4gICAgICBjb25zdCBhbW91bnQgPSAxMDAwMDtcbiAgICAgIGNvbnN0IHRva2VuSWQgPSAxO1xuICAgICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJ1aWxkVW5zaWduZWRUcmFuc2FjdGlvbih7XG4gICAgICAgIHNlbmRlcixcbiAgICAgICAgZGVzdGluYXRpb24sXG4gICAgICAgIGFtb3VudCxcbiAgICAgICAgdG9rZW5JZCxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdW5zaWduZWRIZXggPSBCdWZmZXIuZnJvbSh1bnNpZ25lZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCkpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogdW5zaWduZWRIZXgsXG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAnMTAwMCcgfSxcbiAgICAgIH0pO1xuICAgICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoYW1vdW50LnRvU3RyaW5nKCkpO1xuICAgICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKGRlc3RpbmF0aW9uKTtcbiAgICAgIGV4cGxhaW4udG9rZW5JZC5zaG91bGQuZXF1YWwoMSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gYSBzaWduZWQgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzZW5kZXIgPSBBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQxLmFkZHJlc3M7XG4gICAgICBjb25zdCBkZXN0aW5hdGlvbiA9IEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDIuYWRkcmVzcztcbiAgICAgIGNvbnN0IGFtb3VudCA9IDEwMDAwO1xuICAgICAgY29uc3QgdG9rZW5JZCA9IDE7XG4gICAgICBjb25zdCBzaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJ1aWxkU2lnbmVkVHJhbnNhY3Rpb24oe1xuICAgICAgICBzZW5kZXIsXG4gICAgICAgIGRlc3RpbmF0aW9uLFxuICAgICAgICBhbW91bnQsXG4gICAgICAgIHRva2VuSWQsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHNpZ25lZEhleCA9IEJ1ZmZlci5mcm9tKHNpZ25lZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCkpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogc2lnbmVkSGV4LFxuICAgICAgICBmZWVJbmZvOiB7IGZlZTogJzEwMDAnIH0sXG4gICAgICB9KTtcbiAgICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKGFtb3VudC50b1N0cmluZygpKTtcbiAgICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbChkZXN0aW5hdGlvbik7XG4gICAgICBleHBsYWluLnRva2VuSWQuc2hvdWxkLmVxdWFsKDEpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnV2FsbGV0IEluaXQgQnVpbGRlcjogJywgKCkgPT4ge1xuICAgIGNvbnN0IGJ1aWxkQmFzZUtleVJlZ1RyYW5zYWN0aW9uID0gKHsgc2VuZGVyLCBtZW1vID0gJycgfSkgPT4ge1xuICAgICAgY29uc3QgZmFjdG9yeSA9IG5ldyBBbGdvTGliLlRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkoY29pbnMuZ2V0KCdhbGdvJykpO1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRXYWxsZXRJbml0aWFsaXphdGlvbkJ1aWxkZXIoKTtcbiAgICAgIGNvbnN0IGxlYXNlID0gbmV3IFVpbnQ4QXJyYXkocmFuZG9tQnl0ZXMoMzIpKTtcbiAgICAgIGNvbnN0IG5vdGUgPSBuZXcgVWludDhBcnJheShCdWZmZXIuZnJvbShtZW1vLCAndXRmLTgnKSk7XG4gICAgICB0eEJ1aWxkZXJcbiAgICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IHNlbmRlci5hZGRyZXNzIH0pXG4gICAgICAgIC5pc0ZsYXRGZWUodHJ1ZSlcbiAgICAgICAgLmZlZSh7XG4gICAgICAgICAgZmVlOiAnMTAwMCcsXG4gICAgICAgIH0pXG4gICAgICAgIC5maXJzdFJvdW5kKDEpXG4gICAgICAgIC5sYXN0Um91bmQoMTAwKVxuICAgICAgICAubGVhc2UobGVhc2UpXG4gICAgICAgIC5ub3RlKG5vdGUpXG4gICAgICAgIC52b3RlS2V5KHNlbmRlci52b3RlS2V5KVxuICAgICAgICAuc2VsZWN0aW9uS2V5KHNlbmRlci5zZWxlY3Rpb25LZXkpXG4gICAgICAgIC52b3RlRmlyc3QoMSlcbiAgICAgICAgLnZvdGVMYXN0KDEwMClcbiAgICAgICAgLnZvdGVLZXlEaWx1dGlvbig5KVxuICAgICAgICAudGVzdG5ldCgpO1xuICAgICAgcmV0dXJuIHR4QnVpbGRlcjtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQnVpbGQgYW4gdW5zaWduZWQgYWNjb3VudC1saWIgc2luZ2xlLXNpZ25hdHVyZSBzZW5kIHRyYW5zYWN0aW9uXG4gICAgICogQHBhcmFtIHNlbmRlciBUaGUgc2VuZGVycyBhZGRyZXNzXG4gICAgICogQHBhcmFtIG1lbW8gT3B0aW9uYWwgbm90ZSB3aXRoIHRoZSB0cmFuc2FjdGlvblxuICAgICAqL1xuICAgIGNvbnN0IGJ1aWxkVW5zaWduZWRUcmFuc2FjdGlvbiA9IGFzeW5jIGZ1bmN0aW9uICh7IHNlbmRlciwgbWVtbyA9ICcnIH0pIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGJ1aWxkQmFzZUtleVJlZ1RyYW5zYWN0aW9uKHsgc2VuZGVyLCBtZW1vIH0pO1xuICAgICAgcmV0dXJuIGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBCdWlsZCBhIHNpZ25lZCBhY2NvdW50LWxpYiBzaW5nbGUtc2lnbmF0dXJlIHNlbmQgdHJhbnNhY3Rpb25cbiAgICAgKiBAcGFyYW0gc2VuZGVyIFRoZSBzZW5kZXJzIGFkZHJlc3NcbiAgICAgKiBAcGFyYW0gbWVtbyBPcHRpb25hbCBub3RlIHdpdGggdGhlIHRyYW5zYWN0aW9uXG4gICAgICovXG4gICAgY29uc3QgYnVpbGRTaWduZWRUcmFuc2FjdGlvbiA9IGFzeW5jIGZ1bmN0aW9uICh7IHNlbmRlciwgbWVtbyA9ICcnIH0pIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGJ1aWxkQmFzZUtleVJlZ1RyYW5zYWN0aW9uKHsgc2VuZGVyLCBtZW1vIH0pO1xuICAgICAgdHhCdWlsZGVyLm51bWJlck9mU2lnbmVycygxKTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQxLnBydktleSB9KTtcbiAgICAgIHJldHVybiBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQnVpbGQgYSBtdWx0aS1zaWduZWQgYWNjb3VudC1saWIgc2luZ2xlLXNpZ25hdHVyZSBzZW5kIHRyYW5zYWN0aW9uXG4gICAgICogQHBhcmFtIHNlbmRlcnMgVGhlIGxpc3Qgb2Ygc2VuZGVyc1xuICAgICAqIEBwYXJhbSBtZW1vIE9wdGlvbmFsIG5vdGUgd2l0aCB0aGUgdHJhbnNhY3Rpb25cbiAgICAgKi9cbiAgICBjb25zdCBidWlsZE11bHRpU2lnbmVkVHJhbnNhY3Rpb24gPSBhc3luYyBmdW5jdGlvbiAoeyBzZW5kZXJzLCBtZW1vID0gJycgfSkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gYnVpbGRCYXNlS2V5UmVnVHJhbnNhY3Rpb24oeyBzZW5kZXI6IHNlbmRlcnNbMF0sIG1lbW8gfSk7XG4gICAgICB0eEJ1aWxkZXIubnVtYmVyT2ZTaWduZXJzKDIpO1xuICAgICAgdHhCdWlsZGVyLnNldFNpZ25lcnMoc2VuZGVycy5tYXAoKHsgYWRkcmVzcyB9KSA9PiBhZGRyZXNzKSk7XG4gICAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50MS5wcnZLZXkgfSk7XG4gICAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50My5wcnZLZXkgfSk7XG4gICAgICByZXR1cm4gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgfTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhbiB1bnNpZ25lZCBLZXlSZWcgdHJhbnNmZXIgdHJhbnNhY3Rpb24gaGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2VuZGVyID0gQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50MTtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgua2V5cmVnLnVuc2lnbmVkLFxuICAgICAgICBmZWVJbmZvOiB7IGZlZTogJzEwMDAnIH0sXG4gICAgICB9KTtcbiAgICAgIEJ1ZmZlci5mcm9tKGV4cGxhaW4ubWVtbykudG9TdHJpbmcoKS5zaG91bGQuZXF1YWwoQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgua2V5cmVnLm5vdGUpO1xuICAgICAgZXhwbGFpbi5mZWUuc2hvdWxkLmVxdWFsKDEwMDApO1xuICAgICAgZXhwbGFpbi5jaGFuZ2VBbW91bnQuc2hvdWxkLmVxdWFsKCcwJyk7XG4gICAgICBleHBsYWluLnZvdGVLZXkuc2hvdWxkLmVxdWFsKHNlbmRlci52b3RlS2V5KTtcbiAgICAgIGV4cGxhaW4uc2VsZWN0aW9uS2V5LnNob3VsZC5lcXVhbChzZW5kZXIuc2VsZWN0aW9uS2V5KTtcbiAgICAgIGV4cGxhaW4udm90ZUZpcnN0LnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIGV4cGxhaW4udm90ZUxhc3Quc2hvdWxkLmVxdWFsKDEwMCk7XG4gICAgICBleHBsYWluLnZvdGVLZXlEaWx1dGlvbi5zaG91bGQuZXF1YWwoOSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gYSBzaWduZWQgdHJhbnNmZXIgdHJhbnNhY3Rpb24gaGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2VuZGVyID0gQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50MTtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgua2V5cmVnLnNpZ25lZCxcbiAgICAgICAgZmVlSW5mbzogeyBmZWU6ICcxMDAwJyB9LFxuICAgICAgfSk7XG4gICAgICBCdWZmZXIuZnJvbShleHBsYWluLm1lbW8pLnRvU3RyaW5nKCkuc2hvdWxkLmVxdWFsKEFsZ29SZXNvdXJjZXMuZXhwbGFpblJhd1R4LmtleXJlZy5ub3RlKTtcbiAgICAgIGV4cGxhaW4uZmVlLnNob3VsZC5lcXVhbCgxMDAwKTtcbiAgICAgIGV4cGxhaW4uY2hhbmdlQW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICAgICAgZXhwbGFpbi52b3RlS2V5LnNob3VsZC5lcXVhbChzZW5kZXIudm90ZUtleSk7XG4gICAgICBleHBsYWluLnNlbGVjdGlvbktleS5zaG91bGQuZXF1YWwoc2VuZGVyLnNlbGVjdGlvbktleSk7XG4gICAgICBleHBsYWluLnZvdGVGaXJzdC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBleHBsYWluLnZvdGVMYXN0LnNob3VsZC5lcXVhbCgxMDApO1xuICAgICAgZXhwbGFpbi52b3RlS2V5RGlsdXRpb24uc2hvdWxkLmVxdWFsKDkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGEgbXVsdGlTaWcgdHJhbnNmZXIgdHJhbnNhY3Rpb24gaGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2VuZGVyID0gQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50MTtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgua2V5cmVnLm11bHRpU2lnbmVkLFxuICAgICAgICBmZWVJbmZvOiB7IGZlZTogJzEwMDAnIH0sXG4gICAgICB9KTtcbiAgICAgIEJ1ZmZlci5mcm9tKGV4cGxhaW4ubWVtbykudG9TdHJpbmcoKS5zaG91bGQuZXF1YWwoQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgua2V5cmVnLm5vdGUpO1xuICAgICAgZXhwbGFpbi5mZWUuc2hvdWxkLmVxdWFsKDEwMDApO1xuICAgICAgZXhwbGFpbi5jaGFuZ2VBbW91bnQuc2hvdWxkLmVxdWFsKCcwJyk7XG4gICAgICBleHBsYWluLnZvdGVLZXkuc2hvdWxkLmVxdWFsKHNlbmRlci52b3RlS2V5KTtcbiAgICAgIGV4cGxhaW4uc2VsZWN0aW9uS2V5LnNob3VsZC5lcXVhbChzZW5kZXIuc2VsZWN0aW9uS2V5KTtcbiAgICAgIGV4cGxhaW4udm90ZUZpcnN0LnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIGV4cGxhaW4udm90ZUxhc3Quc2hvdWxkLmVxdWFsKDEwMCk7XG4gICAgICBleHBsYWluLnZvdGVLZXlEaWx1dGlvbi5zaG91bGQuZXF1YWwoOSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gYSBoYWxmIHNpZ25lZCB0cmFuc2ZlciB0cmFuc2FjdGlvbiBoZXgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzZW5kZXIgPSBBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQxO1xuICAgICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgIGhhbGZTaWduZWQ6IHtcbiAgICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgua2V5cmVnLmhhbGZTaWduZWQsXG4gICAgICAgIH0sXG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAnMTAwMCcgfSxcbiAgICAgIH0pO1xuICAgICAgQnVmZmVyLmZyb20oZXhwbGFpbi5tZW1vKS50b1N0cmluZygpLnNob3VsZC5lcXVhbChBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC5rZXlyZWcubm90ZSk7XG4gICAgICBleHBsYWluLmZlZS5zaG91bGQuZXF1YWwoMTAwMCk7XG4gICAgICBleHBsYWluLmNoYW5nZUFtb3VudC5zaG91bGQuZXF1YWwoJzAnKTtcbiAgICAgIGV4cGxhaW4udm90ZUtleS5zaG91bGQuZXF1YWwoc2VuZGVyLnZvdGVLZXkpO1xuICAgICAgZXhwbGFpbi5zZWxlY3Rpb25LZXkuc2hvdWxkLmVxdWFsKHNlbmRlci5zZWxlY3Rpb25LZXkpO1xuICAgICAgZXhwbGFpbi52b3RlRmlyc3Quc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgZXhwbGFpbi52b3RlTGFzdC5zaG91bGQuZXF1YWwoMTAwKTtcbiAgICAgIGV4cGxhaW4udm90ZUtleURpbHV0aW9uLnNob3VsZC5lcXVhbCg5KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhbiB1bnNpZ25lZCB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNlbmRlciA9IEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDE7XG4gICAgICBjb25zdCBtZW1vID0gQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgudHJhbnNmZXIubm90ZTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHJhbnNhY3Rpb24gPSBhd2FpdCBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24oe1xuICAgICAgICBzZW5kZXIsXG4gICAgICAgIG1lbW8sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdW5zaWduZWRIZXggPSBCdWZmZXIuZnJvbSh1bnNpZ25lZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCkpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogdW5zaWduZWRIZXgsXG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAnMTAwMCcgfSxcbiAgICAgIH0pO1xuICAgICAgQnVmZmVyLmZyb20oZXhwbGFpbi5tZW1vKS50b1N0cmluZygpLnNob3VsZC5lcXVhbChBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC50cmFuc2Zlci5ub3RlKTtcbiAgICAgIGV4cGxhaW4udm90ZUtleS5zaG91bGQuZXF1YWwoc2VuZGVyLnZvdGVLZXkpO1xuICAgICAgZXhwbGFpbi5zZWxlY3Rpb25LZXkuc2hvdWxkLmVxdWFsKHNlbmRlci5zZWxlY3Rpb25LZXkpO1xuICAgICAgZXhwbGFpbi52b3RlRmlyc3Quc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgZXhwbGFpbi52b3RlTGFzdC5zaG91bGQuZXF1YWwoMTAwKTtcbiAgICAgIGV4cGxhaW4udm90ZUtleURpbHV0aW9uLnNob3VsZC5lcXVhbCg5KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhIHNpZ25lZCB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNlbmRlciA9IEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDE7XG4gICAgICBjb25zdCBtZW1vID0gQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHgudHJhbnNmZXIubm90ZTtcbiAgICAgIGNvbnN0IHNpZ25lZFRyYW5zYWN0aW9uID0gYXdhaXQgYnVpbGRTaWduZWRUcmFuc2FjdGlvbih7XG4gICAgICAgIHNlbmRlcixcbiAgICAgICAgbWVtbyxcbiAgICAgIH0pO1xuICAgICAgY29uc3Qgc2lnbmVkSGV4ID0gQnVmZmVyLmZyb20oc2lnbmVkVHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4SGV4OiBzaWduZWRIZXgsXG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAnMTAwMCcgfSxcbiAgICAgIH0pO1xuICAgICAgQnVmZmVyLmZyb20oZXhwbGFpbi5tZW1vKS50b1N0cmluZygpLnNob3VsZC5lcXVhbChBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC50cmFuc2Zlci5ub3RlKTtcbiAgICAgIGV4cGxhaW4udm90ZUtleS5zaG91bGQuZXF1YWwoc2VuZGVyLnZvdGVLZXkpO1xuICAgICAgZXhwbGFpbi5zZWxlY3Rpb25LZXkuc2hvdWxkLmVxdWFsKHNlbmRlci5zZWxlY3Rpb25LZXkpO1xuICAgICAgZXhwbGFpbi52b3RlRmlyc3Quc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgZXhwbGFpbi52b3RlTGFzdC5zaG91bGQuZXF1YWwoMTAwKTtcbiAgICAgIGV4cGxhaW4udm90ZUtleURpbHV0aW9uLnNob3VsZC5lcXVhbCg5KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhIG11bHRpU2lnbmVkIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2VuZGVycyA9IFtBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQxLCBBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQzXTtcbiAgICAgIGNvbnN0IG1lbW8gPSBBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC50cmFuc2Zlci5ub3RlO1xuICAgICAgY29uc3Qgc2lnbmVkVHJhbnNhY3Rpb24gPSBhd2FpdCBidWlsZE11bHRpU2lnbmVkVHJhbnNhY3Rpb24oe1xuICAgICAgICBzZW5kZXJzLFxuICAgICAgICBtZW1vLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBzaWduZWRIZXggPSBCdWZmZXIuZnJvbShzaWduZWRUcmFuc2FjdGlvbi50b0Jyb2FkY2FzdEZvcm1hdCgpKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBjb25zdCBleHBsYWluID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhIZXg6IHNpZ25lZEhleCxcbiAgICAgICAgZmVlSW5mbzogeyBmZWU6ICcxMDAwJyB9LFxuICAgICAgfSk7XG4gICAgICBCdWZmZXIuZnJvbShleHBsYWluLm1lbW8pLnRvU3RyaW5nKCkuc2hvdWxkLmVxdWFsKEFsZ29SZXNvdXJjZXMuZXhwbGFpblJhd1R4LnRyYW5zZmVyLm5vdGUpO1xuICAgICAgZXhwbGFpbi52b3RlS2V5LnNob3VsZC5lcXVhbChBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQxLnZvdGVLZXkpO1xuICAgICAgZXhwbGFpbi5zZWxlY3Rpb25LZXkuc2hvdWxkLmVxdWFsKEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDEuc2VsZWN0aW9uS2V5KTtcbiAgICAgIGV4cGxhaW4udm90ZUZpcnN0LnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIGV4cGxhaW4udm90ZUxhc3Quc2hvdWxkLmVxdWFsKDEwMCk7XG4gICAgICBleHBsYWluLnZvdGVLZXlEaWx1dGlvbi5zaG91bGQuZXF1YWwoOSk7XG4gICAgfSk7XG4gIH0pO1xuICBkZXNjcmliZSgnU2lnbiB0cmFuc2FjdGlvbicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHNpZ24gdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzaWduZWQgPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IEFsZ29SZXNvdXJjZXMucmF3VHgudHJhbnNmZXIudW5zaWduZWQsXG4gICAgICAgICAga2V5czogW0FsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDEucHViS2V5LnRvU3RyaW5nKCdoZXgnKV0sXG4gICAgICAgICAgYWRkcmVzc1ZlcnNpb246IDEsXG4gICAgICAgIH0sXG4gICAgICAgIHBydjogQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50MS5wcnZLZXksXG4gICAgICB9KTtcbiAgICAgIHNpZ25lZC50eEhleC5zaG91bGQuZXF1YWwoQWxnb1Jlc291cmNlcy5yYXdUeC50cmFuc2Zlci5zaWduZWQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzaWduIHRyYW5zYWN0aW9uIHdpdGggcm9vdCBrZXknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBrZXlwYWlyID0gYmFzZWNvaW4uZ2VuZXJhdGVSb290S2V5UGFpcihBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQxLnNlY3JldEtleSk7XG5cbiAgICAgIGNvbnN0IHNpZ25lZCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5yYXdUeC50cmFuc2Zlci51bnNpZ25lZCxcbiAgICAgICAgICBrZXlzOiBba2V5cGFpci5wdWJdLFxuICAgICAgICAgIGFkZHJlc3NWZXJzaW9uOiAxLFxuICAgICAgICB9LFxuICAgICAgICBwcnY6IGtleXBhaXIucHJ2LFxuICAgICAgfSk7XG4gICAgICBzaWduZWQudHhIZXguc2hvdWxkLmVxdWFsKEFsZ29SZXNvdXJjZXMucmF3VHgudHJhbnNmZXIuc2lnbmVkKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2lnbiBoYWxmIHNpZ25lZCB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ25lZCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICBoYWxmU2lnbmVkOiB7XG4gICAgICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5yYXdUeC50cmFuc2Zlci5oYWxmU2lnbmVkLFxuICAgICAgICAgIH0sXG4gICAgICAgICAga2V5czogW1xuICAgICAgICAgICAgQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50MS5wdWJLZXkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAgICAgQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50My5wdWJLZXkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgYWRkcmVzc1ZlcnNpb246IDEsXG4gICAgICAgIH0sXG4gICAgICAgIHBydjogQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50My5wcnZLZXksXG4gICAgICB9KTtcbiAgICAgIHNpZ25lZC50eEhleC5zaG91bGQuZXF1YWwoQWxnb1Jlc291cmNlcy5yYXdUeC50cmFuc2Zlci5tdWx0aXNpZyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNpZ24gaGFsZiBzaWduZWQgdHJhbnNhY3Rpb24gd2l0aCByb290IGtleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ25lZCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICBoYWxmU2lnbmVkOiB7XG4gICAgICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5yb290S2V5RGF0YS51bnNpZ25lZFR4LFxuICAgICAgICAgIH0sXG4gICAgICAgICAga2V5czogW1xuICAgICAgICAgICAgQWxnb1Jlc291cmNlcy5yb290S2V5RGF0YS51c2VyS2V5UGFpci5wdWIsXG4gICAgICAgICAgICBBbGdvUmVzb3VyY2VzLnJvb3RLZXlEYXRhLmJhY2t1cFB1YixcbiAgICAgICAgICAgIEFsZ29SZXNvdXJjZXMucm9vdEtleURhdGEuYml0Z29QdWIsXG4gICAgICAgICAgXSxcbiAgICAgICAgICBhZGRyZXNzVmVyc2lvbjogMSxcbiAgICAgICAgfSxcbiAgICAgICAgcHJ2OiBBbGdvUmVzb3VyY2VzLnJvb3RLZXlEYXRhLnVzZXJLZXlQYWlyLnBydixcbiAgICAgIH0pO1xuXG4gICAgICBzaWduZWQudHhIZXguc2hvdWxkLmRlZXBFcXVhbChBbGdvUmVzb3VyY2VzLnJvb3RLZXlEYXRhLmhhbGZTaWduZWRUeCk7XG4gICAgICBjb25zdCBmYWN0b3J5ID0gbmV3IFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkoY29pbnMuZ2V0KCdhbGdvJykpO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCBmYWN0b3J5LmZyb20oc2lnbmVkLnR4SGV4KS5idWlsZCgpO1xuICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICB0eEpzb24uZnJvbS5zaG91bGQuZXF1YWwoQWxnb1Jlc291cmNlcy5yb290S2V5RGF0YS5zZW5kZXJBZGRyZXNzKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IHNpZ24gcGFyYW1zIGlmIHRoZSBrZXkgYXJyYXkgY29udGFpbnMgYWRkcmVzc2VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5cyA9IFtcbiAgICAgICAgQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50MS5hZGRyZXNzLFxuICAgICAgICBBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQyLmFkZHJlc3MsXG4gICAgICAgIEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDMuYWRkcmVzcyxcbiAgICAgIF07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWVkUGFyYW1zID0gYmFzZWNvaW4udmVyaWZ5U2lnblRyYW5zYWN0aW9uUGFyYW1zKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiBBbGdvUmVzb3VyY2VzLnJhd1R4LnRyYW5zZmVyLnVuc2lnbmVkLFxuICAgICAgICAgIGtleXMsXG4gICAgICAgICAgYWRkcmVzc1ZlcnNpb246IDEsXG4gICAgICAgIH0sXG4gICAgICAgIHBydjogQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50Mi5zZWNyZXRLZXkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgfSk7XG4gICAgICB2ZXJpZmllZFBhcmFtcy5zaG91bGQuaGF2ZS5wcm9wZXJ0aWVzKFtcbiAgICAgICAgJ3R4SGV4JyxcbiAgICAgICAgJ2FkZHJlc3NWZXJzaW9uJyxcbiAgICAgICAgJ3NpZ25lcnMnLFxuICAgICAgICAncHJ2JyxcbiAgICAgICAgJ2lzSGFsZlNpZ25lZCcsXG4gICAgICAgICdudW1iZXJTaWduZXJzJyxcbiAgICAgIF0pO1xuICAgICAgY29uc3QgeyB0eEhleCwgc2lnbmVycywgaXNIYWxmU2lnbmVkIH0gPSB2ZXJpZmllZFBhcmFtcztcbiAgICAgIHR4SGV4LnNob3VsZC5iZS5lcXVhbChBbGdvUmVzb3VyY2VzLnJhd1R4LnRyYW5zZmVyLnVuc2lnbmVkKTtcbiAgICAgIHNpZ25lcnMuc2hvdWxkLmJlLmRlZXBFcXVhbChrZXlzKTtcbiAgICAgIGlzSGFsZlNpZ25lZC5zaG91bGQuYmUuZXF1YWwoZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzaWduIGhhbGYgc2lnbmVkIHRyYW5zYWN0aW9uIGlmIHRoZSBrZXkgYXJyYXkgY29udGFpbnMgYWRkcmVzc2VzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2lnbmVkID0gYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIGhhbGZTaWduZWQ6IHtcbiAgICAgICAgICAgIHR4SGV4OiBBbGdvUmVzb3VyY2VzLnJhd1R4LnRyYW5zZmVyLmhhbGZTaWduZWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBrZXlzOiBbQWxnb1Jlc291cmNlcy5hY2NvdW50cy5hY2NvdW50MS5hZGRyZXNzLCBBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQzLmFkZHJlc3NdLFxuICAgICAgICAgIGFkZHJlc3NWZXJzaW9uOiAxLFxuICAgICAgICB9LFxuICAgICAgICBwcnY6IEFsZ29SZXNvdXJjZXMuYWNjb3VudHMuYWNjb3VudDMucHJ2S2V5LFxuICAgICAgfSk7XG4gICAgICBzaWduZWQudHhIZXguc2hvdWxkLmVxdWFsKEFsZ29SZXNvdXJjZXMucmF3VHgudHJhbnNmZXIubXVsdGlzaWcpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2lnbiBtZXNzYWdlJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgc2lnbiBtZXNzYWdlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2lnbmVkID0gYXdhaXQgYmFzZWNvaW4uc2lnbk1lc3NhZ2UoXG4gICAgICAgIHsgcHJ2OiBBbGdvUmVzb3VyY2VzLmFjY291bnRzLmFjY291bnQxLnBydktleSB9LFxuICAgICAgICBBbGdvUmVzb3VyY2VzLm1lc3NhZ2UudW5zaWduZWRcbiAgICAgICk7XG4gICAgICBzaWduZWQudG9TdHJpbmcoJ2hleCcpLnNob3VsZC5lcXVhbChBbGdvUmVzb3VyY2VzLm1lc3NhZ2Uuc2lnbmVkKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0dlbmVyYXRlIHdhbGxldCBrZXkgcGFpcjogJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUga2V5IHBhaXInLCAoKSA9PiB7XG4gICAgICBjb25zdCBrcCA9IGJhc2Vjb2luLmdlbmVyYXRlS2V5UGFpcigpO1xuICAgICAgYmFzZWNvaW4uaXNWYWxpZFB1YihrcC5wdWIpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQcnYoa3AucHJ2KS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGtleSBwYWlyIGZyb20gc2VlZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHNlZWQgPSBCdWZmZXIuZnJvbSgnOWQ2MWIxOWRlZmZkNWE2MGJhODQ0YWY0OTJlYzJjYzQ0NDQ5YzU2OTdiMzI2OTE5NzAzYmFjMDMxY2FlN2Y2MCcsICdoZXgnKTtcbiAgICAgIGNvbnN0IGtwID0gYmFzZWNvaW4uZ2VuZXJhdGVLZXlQYWlyKHNlZWQpO1xuICAgICAgYmFzZWNvaW4uaXNWYWxpZFB1YihrcC5wdWIpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQcnYoa3AucHJ2KS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdHZW5lcmF0ZSB3YWxsZXQgUm9vdCBrZXkgcGFpcjogJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUga2V5IHBhaXInLCAoKSA9PiB7XG4gICAgICBjb25zdCBrcCA9IGJhc2Vjb2luLmdlbmVyYXRlUm9vdEtleVBhaXIoKTtcbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQdWIoa3AucHViKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICBiYXNlY29pbi5pc1ZhbGlkUHJ2KGtwLnBydikuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBrZXkgcGFpciBmcm9tIHNlZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBzZWVkID0gQnVmZmVyLmZyb20oJzlkNjFiMTlkZWZmZDVhNjBiYTg0NGFmNDkyZWMyY2M0NDQ0OWM1Njk3YjMyNjkxOTcwM2JhYzAzMWNhZTdmNjAnLCAnaGV4Jyk7XG4gICAgICBjb25zdCBrcCA9IGJhc2Vjb2luLmdlbmVyYXRlUm9vdEtleVBhaXIoc2VlZCk7XG4gICAgICBiYXNlY29pbi5pc1ZhbGlkUHViKGtwLnB1Yikuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAga3AucHViLnNob3VsZC5lcXVhbCgnZDc1YTk4MDE4MmIxMGFiN2Q1NGJmZWQzYzk2NDA3M2EwZWUxNzJmM2RhYTYyMzI1YWYwMjFhNjhmNzA3NTExYScpO1xuICAgICAgYmFzZWNvaW4uaXNWYWxpZFBydihrcC5wcnYpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIGtwLnBydi5zaG91bGQuZXF1YWwoXG4gICAgICAgICc5ZDYxYjE5ZGVmZmQ1YTYwYmE4NDRhZjQ5MmVjMmNjNDQ0NDljNTY5N2IzMjY5MTk3MDNiYWMwMzFjYWU3ZjYwZDc1YTk4MDE4MmIxMGFiN2Q1NGJmZWQzYzk2NDA3M2EwZWUxNzJmM2RhYTYyMzI1YWYwMjFhNjhmNzA3NTExYSdcbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdFbmFibGUsIGRpc2FibGUgYW5kIHRyYW5zZmVyIFRva2VuICcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gYW4gZW5hYmxlIHRva2VuIHRyYW5zYWN0aW9uIGhleCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHguZW5hYmxlVG9rZW4sXG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAnMTAwMCcgfSxcbiAgICAgIH0pO1xuICAgICAgZXhwbGFpbi5vcGVyYXRpb25zLmxlbmd0aC5zaG91bGQuZXF1YWxzKDEpO1xuICAgICAgZXhwbGFpbi5vcGVyYXRpb25zWzBdLnR5cGUuc2hvdWxkLmVxdWFscygnZW5hYmxlVG9rZW4nKTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9uc1swXS5jb2luLnNob3VsZC5lcXVhbHMoJ3RhbGdvOlVTT04tMTYwMjY3MjgnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhbiBkaXNhYmxlIHRva2VuIHRyYW5zYWN0aW9uIGhleCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHguZGlzYWJsZVRva2VuLFxuICAgICAgICBmZWVJbmZvOiB7IGZlZTogJzEwMDAnIH0sXG4gICAgICB9KTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9ucy5sZW5ndGguc2hvdWxkLmVxdWFscygxKTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9uc1swXS50eXBlLnNob3VsZC5lcXVhbHMoJ2Rpc2FibGVUb2tlbicpO1xuICAgICAgZXhwbGFpbi5vcGVyYXRpb25zWzBdLmNvaW4uc2hvdWxkLmVxdWFscygndGFsZ286VVNPTi0xNjAyNjcyOCcpO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhbiB0cmFuc2ZlciB0b2tlbiB0cmFuc2FjdGlvbiBoZXgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBsYWluID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhIZXg6IEFsZ29SZXNvdXJjZXMuZXhwbGFpblJhd1R4LmFzc2V0VHJhbnNmZXIuc2lnbmVkLFxuICAgICAgICBmZWVJbmZvOiB7IGZlZTogJzEwMDAnIH0sXG4gICAgICB9KTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9ucy5sZW5ndGguc2hvdWxkLmVxdWFscygxKTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9uc1swXS50eXBlLnNob3VsZC5lcXVhbHMoJ3RyYW5zZmVyVG9rZW4nKTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9uc1swXS5jb2luLnNob3VsZC5lcXVhbHMoJ0FsZ29Ub2tlbiB1bmtub3duJyk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGFuIGVuYWJsZSBVU0RUIHRva2VuIHRyYW5zYWN0aW9uIGhleCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHguZW5hYmxlVG9rZW5VU0RULFxuICAgICAgICBmZWVJbmZvOiB7IGZlZTogJzEwMDAnIH0sXG4gICAgICB9KTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9ucy5sZW5ndGguc2hvdWxkLmVxdWFscygxKTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9uc1swXS50eXBlLnNob3VsZC5lcXVhbHMoJ2VuYWJsZVRva2VuJyk7XG4gICAgICBleHBsYWluLm9wZXJhdGlvbnNbMF0uY29pbi5zaG91bGQuZXF1YWxzKCd0YWxnbzpVU0R0LTE4MDQ0NycpO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhbiBlbmFibGUgVVNEQyB0b2tlbiB0cmFuc2FjdGlvbiBoZXgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBsYWluID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhIZXg6IEFsZ29SZXNvdXJjZXMuZXhwbGFpblJhd1R4LmVuYWJsZVRva2VuVVNEQyxcbiAgICAgICAgZmVlSW5mbzogeyBmZWU6ICcxMDAwJyB9LFxuICAgICAgfSk7XG4gICAgICBleHBsYWluLm9wZXJhdGlvbnMubGVuZ3RoLnNob3VsZC5lcXVhbHMoMSk7XG4gICAgICBleHBsYWluLm9wZXJhdGlvbnNbMF0udHlwZS5zaG91bGQuZXF1YWxzKCdlbmFibGVUb2tlbicpO1xuICAgICAgZXhwbGFpbi5vcGVyYXRpb25zWzBdLmNvaW4uc2hvdWxkLmVxdWFscygndGFsZ286VVNEQy0xMDQ1ODk0MScpO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhbiBkaXNhYmxlIFVTREMgdG9rZW4gdHJhbnNhY3Rpb24gaGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4SGV4OiBBbGdvUmVzb3VyY2VzLmV4cGxhaW5SYXdUeC5kaXNhYmxlVG9rZW5VU0RDLFxuICAgICAgICBmZWVJbmZvOiB7IGZlZTogJzEwMDAnIH0sXG4gICAgICB9KTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9ucy5sZW5ndGguc2hvdWxkLmVxdWFscygxKTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9uc1swXS50eXBlLnNob3VsZC5lcXVhbHMoJ2Rpc2FibGVUb2tlbicpO1xuICAgICAgZXhwbGFpbi5vcGVyYXRpb25zWzBdLmNvaW4uc2hvdWxkLmVxdWFscygndGFsZ286VVNEQy0xMDQ1ODk0MScpO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhbiB0cmFuc2ZlciBVU0RDIHRva2VuIHRyYW5zYWN0aW9uIGhleCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogQWxnb1Jlc291cmNlcy5leHBsYWluUmF3VHguVVNEQ0Fzc2V0VHJhbnNmZXIuc2lnbmVkLFxuICAgICAgICBmZWVJbmZvOiB7IGZlZTogJzEwMDAnIH0sXG4gICAgICB9KTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9ucy5sZW5ndGguc2hvdWxkLmVxdWFscygxKTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9uc1swXS50eXBlLnNob3VsZC5lcXVhbHMoJ3RyYW5zZmVyVG9rZW4nKTtcbiAgICAgIGV4cGxhaW4ub3BlcmF0aW9uc1swXS5jb2luLnNob3VsZC5lcXVhbHMoJ3RhbGdvOlVTREMtMTA0NTg5NDEnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2Rlcml2ZUtleVdpdGhTZWVkJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgZGVyaXZlIGtleSB3aXRoIHNlZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAoKCkgPT4ge1xuICAgICAgICBiYXNlY29pbi5kZXJpdmVLZXlXaXRoU2VlZCgndGVzdCcpO1xuICAgICAgfSkuc2hvdWxkLnRocm93KCdtZXRob2QgZGVyaXZlS2V5V2l0aFNlZWQgbm90IHN1cHBvcnRlZCBmb3IgZWRkc2EgY3VydmUnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JlY292ZXJ5JywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGZlZSA9IDEwMDA7XG4gICAgY29uc3QgdXNlcktleSA9XG4gICAgICAne1wiaXZcIjpcIlpKZzBhMCt6VCs2ODRNVWw0NExtNEE9PVwiLFwidlwiOjEsXCJpdGVyXCI6MTAwMDAsXCJrc1wiOjEyOCxcInRzXCI6NjQsXCJtb2RlXCI6XCJjY21cIixcImFkYXRhXCI6XCJcIixcImNpcGhlclwiOlwiYWVzXCIsXCJzYWx0XCI6XCJhYlF5ME9MMjQ2OD1cIixcImN0XCI6XCJMTmxTbFRKRUQ4alN3SENtVWZsenFGdFJQTCtQb2p6T2dmZDVtRDJubUxWZEFveUtDV0h2QWllS3Q3bEo3emc0MTdDVWk2UWo3Ny9zM2xicW14VnNmRXNrXCJ9JztcbiAgICBjb25zdCB1c2VyUHViID0gJ1M0RDdERFJBSFdaSUIyUkNaSUNTUk9ERkNOUVhHQU5IR0E3VkNXQks1STM3U1FUNktWSFhRTktNVEUnO1xuICAgIGNvbnN0IGJhY2t1cEtleSA9XG4gICAgICAne1wiaXZcIjpcIm1aWThYVHZIeFg4QlBjMXJkR1FRd3c9PVwiLFwidlwiOjEsXCJpdGVyXCI6MTAwMDAsXCJrc1wiOjEyOCxcInRzXCI6NjQsXCJtb2RlXCI6XCJjY21cIixcImFkYXRhXCI6XCJcIixcImNpcGhlclwiOlwiYWVzXCIsXCJzYWx0XCI6XCJhYlF5ME9MMjQ2OD1cIixcImN0XCI6XCJVUVhvMEVhUFhiNlRJWkRZWWhLWVM5ZC9mUk1OVDZwdHBsOUJnSnczQVZvb1NiTzRucHBXblRSWWxRTzdocE9ONFhZODVoWUR1LzdoeTkxSVgxejFiRERxXCJ9JztcbiAgICBjb25zdCBiYWNrdXBQdWIgPSAnNkZWR1pVWk9IWlNYVFRCUkxXWkRYR1lTV1ZWWU5ONFpFU0lFTVpFTUlCSkNVQkhDNUM3N09JRTVSUSc7XG4gICAgY29uc3Qgcm9vdEFkZHJlc3MgPSAnRldMTkRMN1VYQ1NPUE9RWEE1VlUyRE1BTlpBWUNDTUJZMzc3SEtUR0dNWjRHRVBFSkJGQVJET0dCQSc7XG4gICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9ICdUZXN0aW5nQDQzMjEwISc7XG4gICAgY29uc3QgcmVjb3ZlcnlEZXN0aW5hdGlvbiA9ICdHQjNZRVRENVRTVEJBSVlHWUhWV1UzTzNJN1hHT0I0NEhPWkE1TU9FRjVNMjNDTExaS1JRTEVWQU9BJztcbiAgICBjb25zdCBiaXRnb1B1YiA9ICdGSlNXTExQUkJYRUdNV1pZNUJYQTY2NzNZS0lLN0pPVVJWQ1FFT1dYQzVUUVBDWENPSzNWSE9PMlZRJztcbiAgICBjb25zdCBuYXRpdmVCYWxhbmNlID0gMTAwMDAwMDA7IC8vIDEwIEFMR09cbiAgICBjb25zdCBNSU5fQUNDT1VOVF9CQUxBTkNFID0gMTAwMDAwOyAvLyAxIEFHTE9cblxuICAgIGNvbnN0IG5vZGVQYXJhbXMgPSB7XG4gICAgICB0b2tlbjogJzI4MTBjMmQxNjhlODQxN2M1ZjExMWQzOGQ2ODMyN2I4Y2ZlMmQwZGRjMDI5ODY0OTBjMjJmOGRkZjQxMjhiY2QnLFxuICAgICAgYmFzZVNlcnZlcjogJ2h0dHA6Ly9sb2NhbGhvc3QvJyxcbiAgICAgIHBvcnQ6IDg0NDMsXG4gICAgfTtcblxuICAgIGRlc2NyaWJlKCdOb24tQml0R28nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzYW5kQm94ID0gU2lub24uY3JlYXRlU2FuZGJveCgpO1xuICAgICAgY29uc3QgZXhwZWN0ZWRBbW91bnQgPSBuZXcgQmlnTnVtYmVyKG5hdGl2ZUJhbGFuY2UpLm1pbnVzKGZlZSkubWludXMoTUlOX0FDQ09VTlRfQkFMQU5DRSkudG9TdHJpbmcoKTtcblxuICAgICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2FuZEJveC52ZXJpZnlBbmRSZXN0b3JlKCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBidWlsZCBhbmQgc2lnbiB0aGUgcmVjb3ZlcnkgdHgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGdldEJhbGFuY2VTdHViID0gc2FuZEJveC5zdHViKEFsZ28ucHJvdG90eXBlLCAnZ2V0QWNjb3VudEJhbGFuY2UnKS5yZXNvbHZlcyhuYXRpdmVCYWxhbmNlKTtcblxuICAgICAgICBjb25zdCByZWNvdmVyeSA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5LFxuICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgZmVlLFxuICAgICAgICAgIGJpdGdvS2V5OiBiaXRnb1B1YixcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICAgIGZpcnN0Um91bmQ6IDUwMDI1OTYsXG4gICAgICAgICAgbm9kZVBhcmFtcyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZmVlJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luJywgJ3RhbGdvJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdmaXJzdFJvdW5kJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdsYXN0Um91bmQnKTtcbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIuY2FsbENvdW50LnNob3VsZC5lcXVhbCgxKTtcbiAgICAgICAgY29uc3QgZmFjdG9yeSA9IG5ldyBBbGdvTGliLlRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkoY29pbnMuZ2V0KCdhbGdvJykpO1xuICAgICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmVjb3ZlcnkudHgpO1xuICAgICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgICBjb25zdCB0eEJyb2FkY2FzdEZvcm1hdCA9IEJ1ZmZlci5mcm9tKHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICAgICAgdHhCcm9hZGNhc3RGb3JtYXQuc2hvdWxkLmRlZXBFcXVhbChyZWNvdmVyeS50eCk7XG4gICAgICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuICAgICAgICB0eEpzb24uYW1vdW50LnNob3VsZC5lcXVhbChleHBlY3RlZEFtb3VudCk7XG4gICAgICAgIHR4SnNvbi50by5zaG91bGQuZXF1YWwocmVjb3ZlcnlEZXN0aW5hdGlvbik7XG4gICAgICAgIHR4SnNvbi5mcm9tLnNob3VsZC5lcXVhbChyb290QWRkcmVzcyk7XG4gICAgICAgIHR4SnNvbi5mZWUuc2hvdWxkLmVxdWFsKGZlZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgaW52YWxpZCByb290QWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgaW52YWxpZFJvb3RBZGRyZXNzID0gJ3JhbmRvbXN0cmluZyc7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzOiBpbnZhbGlkUm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgICAgIGZlZSxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICAgICAgZmlyc3RSb3VuZDogNTAwMjU5NixcbiAgICAgICAgICAgICAgbm9kZVBhcmFtcyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBtZXNzYWdlOiAnaW52YWxpZCByb290QWRkcmVzcywgZ290OiAnICsgaW52YWxpZFJvb3RBZGRyZXNzIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IGZvciBpbnZhbGlkIHJlY292ZXJ5RGVzdGluYXRpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGludmFsaWRSZWNvdmVyeURlc3RpbmF0aW9uID0gJ3JhbmRvbXN0cmluZyc7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgICAgICBmZWUsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGludmFsaWRSZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICAgICAgICBmaXJzdFJvdW5kOiA1MDAyNTk2LFxuICAgICAgICAgICAgICBub2RlUGFyYW1zLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdpbnZhbGlkIHJlY292ZXJ5RGVzdGluYXRpb24sIGdvdDogJyArIGludmFsaWRSZWNvdmVyeURlc3RpbmF0aW9uIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IGlmIHRoZXJlIGlzIG5vIGVub3VnaCBiYWxhbmNlIHRvIHJlY292ZXInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGdldEJhbGFuY2VTdHViID0gc2FuZEJveC5zdHViKEFsZ28ucHJvdG90eXBlLCAnZ2V0QWNjb3VudEJhbGFuY2UnKS5yZXNvbHZlcygxMDA1MDApO1xuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgdXNlcktleSxcbiAgICAgICAgICAgICAgYmFja3VwS2V5LFxuICAgICAgICAgICAgICByb290QWRkcmVzcyxcbiAgICAgICAgICAgICAgZmVlLFxuICAgICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgICAgICBiaXRnb0tleTogYml0Z29QdWIsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgICAgICAgIGZpcnN0Um91bmQ6IDUwMDM1OTYsXG4gICAgICAgICAgICAgIG5vZGVQYXJhbXMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbWVzc2FnZTogJ0luc3VmZmljaWVudCBiYWxhbmNlIHRvIHJlY292ZXIsIGdvdCBiYWxhbmNlOiAxMDA1MDAgZmVlOiAxMDAwIG1pbiBhY2NvdW50IGJhbGFuY2U6IDEwMDAwMCcgfVxuICAgICAgICApO1xuXG4gICAgICAgIGdldEJhbGFuY2VTdHViLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiB0aGUgd2FsbGV0UGFzc3BocmFzZSBpcyB1bmRlZmluZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICBmZWUsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgICAgICAgIGZpcnN0Um91bmQ6IDUwMDM1OTYsXG4gICAgICAgICAgICAgIG5vZGVQYXJhbXMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbWVzc2FnZTogJ3dhbGxldFBhc3NwaHJhc2UgaXMgcmVxdWlyZWQgZm9yIG5vbi1iaXRnbyByZWNvdmVyeScgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgdGhlIHdhbGxldFBhc3NwaHJhc2UgaXMgd3JvbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICBiaXRnb0tleTogYml0Z29QdWIsXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICd3cm9uZ3Bhc3N3b3JkJyxcbiAgICAgICAgICAgICAgZmVlLFxuICAgICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICAgICAgICBmaXJzdFJvdW5kOiA1MDAzNTk2LFxuICAgICAgICAgICAgICBub2RlUGFyYW1zLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBtZXNzYWdlOlxuICAgICAgICAgICAgICBcInVuYWJsZSB0byBkZWNyeXB0IHVzZXJLZXkgb3IgYmFja3VwS2V5IHdpdGggdGhlIHdhbGxldFBhc3NwaHJhc2UgcHJvdmlkZWQsIGdvdCBlcnJvcjogcGFzc3dvcmQgZXJyb3IgLSBjY206IHRhZyBkb2Vzbid0IG1hdGNoXCIsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgYml0Z28ga2V5IGlzIG5vdCBwcm92aWRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgICAgIGZlZSxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICAgICAgZmlyc3RSb3VuZDogNTAwMzU5NixcbiAgICAgICAgICAgICAgbm9kZVBhcmFtcyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbWVzc2FnZTogJ2JpdGdvIHB1YmxpYyBrZXkgZnJvbSB0aGUga2V5Q2FyZCBpcyByZXF1aXJlZCBmb3Igbm9uLWJpdGdvIHJlY292ZXJ5JyxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBiZSBhYmxlIHRvIHBhc3MgYSB1dGYtOCBlbmNvZGVkIG5vdGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IG5vdGUgPSAnTm9uLUJpdEdvIFJlY292ZXJ5IFN3ZWVwIFR4JztcbiAgICAgICAgc2FuZEJveC5zdHViKEFsZ28ucHJvdG90eXBlLCAnZ2V0QWNjb3VudEJhbGFuY2UnKS5yZXNvbHZlcyhuYXRpdmVCYWxhbmNlKTtcbiAgICAgICAgY29uc3QgcmVjb3ZlcnkgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICByb290QWRkcmVzcyxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIGZlZSxcbiAgICAgICAgICBiaXRnb0tleTogYml0Z29QdWIsXG4gICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICBmaXJzdFJvdW5kOiA1MDAyNTk2LFxuICAgICAgICAgIG5vZGVQYXJhbXMsXG4gICAgICAgICAgbm90ZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgICAgcmVjb3Zlcnkubm90ZS5zaG91bGQuYmUuZXF1YWwobm90ZSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdVbnNpZ25lZCBTd2VlcCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNhbmRCb3ggPSBTaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gICAgICBjb25zdCBleHBlY3RlZEFtb3VudCA9IG5ldyBCaWdOdW1iZXIobmF0aXZlQmFsYW5jZSkubWludXMoZmVlKS5taW51cyhNSU5fQUNDT1VOVF9CQUxBTkNFKS50b1N0cmluZygpO1xuICAgICAgbGV0IGdldEJhbGFuY2VTdHViOiBTaW5vblN0dWI7XG5cbiAgICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBnZXRCYWxhbmNlU3R1YiA9IHNhbmRCb3guc3R1YihBbGdvLnByb3RvdHlwZSwgJ2dldEFjY291bnRCYWxhbmNlJykucmVzb2x2ZXMobmF0aXZlQmFsYW5jZSk7XG4gICAgICB9KTtcblxuICAgICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2FuZEJveC52ZXJpZnlBbmRSZXN0b3JlKCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBidWlsZCB1bnNpZ25lZCBzd2VlcCB0eCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgcmVjb3ZlcnkgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiB1c2VyUHViLFxuICAgICAgICAgIGJhY2t1cEtleTogYmFja3VwUHViLFxuICAgICAgICAgIGJpdGdvS2V5OiBiaXRnb1B1YixcbiAgICAgICAgICByb290QWRkcmVzcyxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIGZlZSxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICAgIGZpcnN0Um91bmQ6IDUwMDM1OTYsXG4gICAgICAgICAgbm9kZVBhcmFtcyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIuY2FsbENvdW50LnNob3VsZC5lcXVhbCgxKTtcblxuICAgICAgICByZWNvdmVyeS5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHhIZXgnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R5cGUnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2Ftb3VudCcpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZmVlSW5mbycpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29pbicsICd0YWxnbycpO1xuICAgICAgICByZWNvdmVyeS5maXJzdFJvdW5kLnNob3VsZC5ub3QuYmUudW5kZWZpbmVkKCk7XG4gICAgICAgIHJlY292ZXJ5Lmxhc3RSb3VuZC5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgna2V5cycpO1xuICAgICAgICByZWNvdmVyeS5rZXlzLnNob3VsZC5kZWVwRXF1YWwoW3VzZXJQdWIsIGJhY2t1cFB1YiwgYml0Z29QdWJdKTtcbiAgICAgICAgcmVjb3ZlcnkuYWRkcmVzc1ZlcnNpb24uc2hvdWxkLmVxdWFsKDEpO1xuXG4gICAgICAgIGdldEJhbGFuY2VTdHViLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgQWxnb0xpYi5UcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW5zLmdldCgnYWxnbycpKTtcbiAgICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5mcm9tKHJlY292ZXJ5LnR4SGV4KTtcbiAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgQnVmZmVyLmZyb20odHgudG9Ccm9hZGNhc3RGb3JtYXQoKSkudG9TdHJpbmcoJ2hleCcpLnNob3VsZC5kZWVwRXF1YWwocmVjb3ZlcnkudHhIZXgpO1xuICAgICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgICAgdHhKc29uLmFtb3VudC5zaG91bGQuZXF1YWwoZXhwZWN0ZWRBbW91bnQpO1xuICAgICAgICB0eEpzb24udG8uc2hvdWxkLmVxdWFsKHJlY292ZXJ5RGVzdGluYXRpb24pO1xuICAgICAgICB0eEpzb24uZnJvbS5zaG91bGQuZXF1YWwocm9vdEFkZHJlc3MpO1xuICAgICAgICB0eEpzb24uZmVlLnNob3VsZC5lcXVhbChmZWUpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnUmVjb3Zlcnkgd2l0aCByb290IGtleXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzYW5kQm94ID0gU2lub24uY3JlYXRlU2FuZGJveCgpO1xuICAgICAgbGV0IHVzZXJLcDogS2V5UGFpcjtcbiAgICAgIGxldCBiYWNrdXBLcDogS2V5UGFpcjtcbiAgICAgIGxldCByb290QWRkcmVzczogc3RyaW5nO1xuICAgICAgbGV0IGVuY3J5cHRlZFVzZXJQcnY6IHN0cmluZztcbiAgICAgIGxldCBlbmNyeXB0ZWRCYWNrdXBQcnY6IHN0cmluZztcblxuICAgICAgY29uc3QgZXhwZWN0ZWRBbW91bnQgPSBuZXcgQmlnTnVtYmVyKG5hdGl2ZUJhbGFuY2UpLm1pbnVzKGZlZSkubWludXMoTUlOX0FDQ09VTlRfQkFMQU5DRSkudG9TdHJpbmcoKTtcbiAgICAgIGxldCBnZXRCYWxhbmNlU3R1YjogU2lub25TdHViO1xuXG4gICAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgdXNlclNlZWQgPSBCdWZmZXIuZnJvbSgnOWQ2MWIxOWRlZmZkNWE2MGJhODQ0YWY0OTJlYzJjYzQ0NDQ5YzU2OTdiMzI2OTE5NzAzYmFjMDMxY2FlN2Y2MCcsICdoZXgnKTtcbiAgICAgICAgdXNlcktwID0gYmFzZWNvaW4uZ2VuZXJhdGVSb290S2V5UGFpcih1c2VyU2VlZCk7XG4gICAgICAgIGVuY3J5cHRlZFVzZXJQcnYgPSBiaXRnby5lbmNyeXB0KHtcbiAgICAgICAgICBpbnB1dDogdXNlcktwLnBydixcbiAgICAgICAgICBwYXNzd29yZDogd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgfSk7XG4gICAgICAgIGFzc2VydCh1c2VyS3AucHViKTtcblxuICAgICAgICBjb25zdCBiYWNrdXBTZWVkID0gQnVmZmVyLmZyb20oJzZkNjFiMTlkZWZmZDVhNjBiYTg0NGFmNDkyZWMyY2M0NDQ0OWM1Njk3YjMyNjkxOTcwM2JhYzAzMWNhZTdmNjAnLCAnaGV4Jyk7XG4gICAgICAgIGJhY2t1cEtwID0gYmFzZWNvaW4uZ2VuZXJhdGVSb290S2V5UGFpcihiYWNrdXBTZWVkKTtcbiAgICAgICAgZW5jcnlwdGVkQmFja3VwUHJ2ID0gYml0Z28uZW5jcnlwdCh7XG4gICAgICAgICAgaW5wdXQ6IGJhY2t1cEtwLnBydixcbiAgICAgICAgICBwYXNzd29yZDogd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGJpdGdvUHViID0gJ0ZKU1dMTFBSQlhFR01XWlk1QlhBNjY3M1lLSUs3Sk9VUlZDUUVPV1hDNVRRUENYQ09LM1ZIT08yVlEnO1xuICAgICAgICBjb25zdCB1c2VyQWRkcmVzcyA9IEFsZ29MaWIuYWxnb1V0aWxzLnByaXZhdGVLZXlUb0FsZ29BZGRyZXNzKHVzZXJLcC5wcnYpO1xuICAgICAgICBjb25zdCBiYWNrdXBBZGRyZXNzID0gQWxnb0xpYi5hbGdvVXRpbHMucHJpdmF0ZUtleVRvQWxnb0FkZHJlc3MoYmFja3VwS3AucHJ2KTtcblxuICAgICAgICByb290QWRkcmVzcyA9IEFsZ29MaWIuYWxnb1V0aWxzLm11bHRpc2lnQWRkcmVzcygxLCAyLCBbdXNlckFkZHJlc3MsIGJhY2t1cEFkZHJlc3MsIGJpdGdvUHViXSk7XG4gICAgICB9KTtcblxuICAgICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2FuZEJveC52ZXJpZnlBbmRSZXN0b3JlKCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBidWlsZCBhbmQgc2lnbiBub24tYml0Z28gcmVjb3ZlcnkgdHggd2l0aCByb290IGtleXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGdldEJhbGFuY2VTdHViID0gc2FuZEJveC5zdHViKEFsZ28ucHJvdG90eXBlLCAnZ2V0QWNjb3VudEJhbGFuY2UnKS5yZXNvbHZlcyhuYXRpdmVCYWxhbmNlKTtcbiAgICAgICAgY29uc3QgcmVjb3ZlcnkgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiBlbmNyeXB0ZWRVc2VyUHJ2LFxuICAgICAgICAgIGJhY2t1cEtleTogZW5jcnlwdGVkQmFja3VwUHJ2LFxuICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgZmVlLFxuICAgICAgICAgIGJpdGdvS2V5OiBiaXRnb1B1YixcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICAgIGZpcnN0Um91bmQ6IDUwMDI1OTYsXG4gICAgICAgICAgbm9kZVBhcmFtcyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZmVlJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luJywgJ3RhbGdvJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdmaXJzdFJvdW5kJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdsYXN0Um91bmQnKTtcbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIuY2FsbENvdW50LnNob3VsZC5lcXVhbCgxKTtcbiAgICAgICAgY29uc3QgZmFjdG9yeSA9IG5ldyBBbGdvTGliLlRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkoY29pbnMuZ2V0KCdhbGdvJykpO1xuICAgICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmVjb3ZlcnkudHgpO1xuICAgICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgICBjb25zdCB0eEJyb2FkY2FzdEZvcm1hdCA9IEJ1ZmZlci5mcm9tKHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICAgICAgdHhCcm9hZGNhc3RGb3JtYXQuc2hvdWxkLmRlZXBFcXVhbChyZWNvdmVyeS50eCk7XG4gICAgICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuICAgICAgICB0eEpzb24uYW1vdW50LnNob3VsZC5lcXVhbChleHBlY3RlZEFtb3VudCk7XG4gICAgICAgIHR4SnNvbi50by5zaG91bGQuZXF1YWwocmVjb3ZlcnlEZXN0aW5hdGlvbik7XG4gICAgICAgIHR4SnNvbi5mcm9tLnNob3VsZC5lcXVhbChyb290QWRkcmVzcyk7XG4gICAgICAgIHR4SnNvbi5mZWUuc2hvdWxkLmVxdWFsKGZlZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBidWlsZCB1bnNpZ25lZCBzd2VlcCB0eCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIgPSBzYW5kQm94LnN0dWIoQWxnby5wcm90b3R5cGUsICdnZXRBY2NvdW50QmFsYW5jZScpLnJlc29sdmVzKG5hdGl2ZUJhbGFuY2UpO1xuICAgICAgICBjb25zdCByZWNvdmVyeSA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgIHVzZXJLZXk6IHVzZXJLcC5wdWIhLFxuICAgICAgICAgIGJhY2t1cEtleTogYmFja3VwS3AucHViISxcbiAgICAgICAgICBiaXRnb0tleTogYml0Z29QdWIsXG4gICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICBmZWUsXG4gICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICBmaXJzdFJvdW5kOiA1MDAzNTk2LFxuICAgICAgICAgIG5vZGVQYXJhbXMsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGdldEJhbGFuY2VTdHViLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMSk7XG5cbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eXBlJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhbW91bnQnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2ZlZUluZm8nKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2NvaW4nLCAndGFsZ28nKTtcbiAgICAgICAgcmVjb3ZlcnkuZmlyc3RSb3VuZC5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgICByZWNvdmVyeS5sYXN0Um91bmQuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2tleXMnKTtcbiAgICAgICAgcmVjb3Zlcnkua2V5cy5zaG91bGQuZGVlcEVxdWFsKFt1c2VyS3AucHViLCBiYWNrdXBLcC5wdWIsIGJpdGdvUHViXSk7XG4gICAgICAgIHJlY292ZXJ5LmFkZHJlc3NWZXJzaW9uLnNob3VsZC5lcXVhbCgxKTtcblxuICAgICAgICBnZXRCYWxhbmNlU3R1Yi5jYWxsQ291bnQuc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgICBjb25zdCBmYWN0b3J5ID0gbmV3IEFsZ29MaWIuVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2lucy5nZXQoJ2FsZ28nKSk7XG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZnJvbShyZWNvdmVyeS50eEhleCk7XG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIEJ1ZmZlci5mcm9tKHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkpLnRvU3RyaW5nKCdoZXgnKS5zaG91bGQuZGVlcEVxdWFsKHJlY292ZXJ5LnR4SGV4KTtcbiAgICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICAgIHR4SnNvbi5hbW91bnQuc2hvdWxkLmVxdWFsKGV4cGVjdGVkQW1vdW50KTtcbiAgICAgICAgdHhKc29uLnRvLnNob3VsZC5lcXVhbChyZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgICAgICAgdHhKc29uLmZyb20uc2hvdWxkLmVxdWFsKHJvb3RBZGRyZXNzKTtcbiAgICAgICAgdHhKc29uLmZlZS5zaG91bGQuZXF1YWwoZmVlKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQXVkaXRLZXknLCAoKSA9PiB7XG4gICAgY29uc3QgeyBrZXkgfSA9IGFsZ29CYWNrdXBLZXk7XG4gICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9ICdaUThNaHhUODRtNFAnO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZm9yIHZhbGlkIGlucHV0cycsICgpID0+IHtcbiAgICAgIGJhc2Vjb2luLmFzc2VydElzVmFsaWRLZXkoe1xuICAgICAgICBlbmNyeXB0ZWRQcnY6IGtleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBpZiB0aGUgd2FsbGV0UGFzc3BocmFzZSBpcyBpbmNvcnJlY3QnLCAoKSA9PiB7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgYmFzZWNvaW4uYXNzZXJ0SXNWYWxpZEtleSh7XG4gICAgICAgICAgICBlbmNyeXB0ZWRQcnY6IGtleSxcbiAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmb28nLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICB7IG1lc3NhZ2U6IFwiZmFpbGVkIHRvIGRlY3J5cHQgcHJ2OiBjY206IHRhZyBkb2Vzbid0IG1hdGNoXCIgfVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgaWYgdGhlIGtleSBpcyBhbHRlcmVkJywgKCkgPT4ge1xuICAgICAgY29uc3QgYWx0ZXJlZEtleSA9IGtleS5yZXBsYWNlKC9bMC05XS9nLCAnMCcpO1xuICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgKCkgPT4ge1xuICAgICAgICAgIGJhc2Vjb2luLmFzc2VydElzVmFsaWRLZXkoe1xuICAgICAgICAgICAgZW5jcnlwdGVkUHJ2OiBhbHRlcmVkS2V5LFxuICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgeyBtZXNzYWdlOiAnZmFpbGVkIHRvIGRlY3J5cHQgcHJ2OiBqc29uIGRlY3J5cHQ6IGludmFsaWQgcGFyYW1ldGVycycgfVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgaWYgdGhlIGtleSBpcyBub3QgYSB2YWxpZCBrZXknLCAoKSA9PiB7XG4gICAgICBjb25zdCBpbnZhbGlkS2V5ID0gJyNAKSQjKCQqQCkjKCQqJztcbiAgICAgIGNvbnN0IGVuY3J5cHRlZFBydiA9IGVuY3J5cHQod2FsbGV0UGFzc3BocmFzZSwgaW52YWxpZEtleSk7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgYmFzZWNvaW4uYXNzZXJ0SXNWYWxpZEtleSh7XG4gICAgICAgICAgICBlbmNyeXB0ZWRQcnYsXG4gICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICB7IG1lc3NhZ2U6ICdJbnZhbGlkIHByaXZhdGUga2V5OiBJbnZhbGlkIGJhc2UzMiBjaGFyYWN0ZXJzJyB9XG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnYmxpbmQgc2lnbmluZyB0b2tlbiBlbmFibGVtZW50IHByb3RlY3Rpb24nLCAoKSA9PiB7XG4gICAgbGV0IHdhbGxldDogV2FsbGV0O1xuICAgIGNvbnN0IGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1snbW9jayddLnVyaTtcblxuICAgIGJlZm9yZSgoKSA9PiB7XG4gICAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICAgIGJpdGdvLnNhZmVSZWdpc3RlcigndGFsZ28nLCBUYWxnby5jcmVhdGVJbnN0YW5jZSk7XG4gICAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICAgIGJhc2Vjb2luID0gYml0Z28uY29pbigndGFsZ28nKTtcblxuICAgICAgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHtcbiAgICAgICAgaWQ6ICcxMjMnLFxuICAgICAgICBjb2luOiAndGFsZ28nLFxuICAgICAgICBrZXlzOiBbJzEnLCAnMicsICczJ10sXG4gICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgIHJvb3RBZGRyZXNzOiAnMTIzJyxcbiAgICAgICAgfSxcbiAgICAgICAgdHlwZTogJ2hvdCcsXG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBhIHZhbGlkIHRva2VuIGVuYWJsZW1lbnQgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB2ZXJpZnlUcmFuc2FjdGlvblN0dWIgPSBzcHkoYmFzZWNvaW4sICd2ZXJpZnlUcmFuc2FjdGlvbicpO1xuICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgLnBvc3QoYC9hcGkvdjIvdGFsZ28vd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3R4L2J1aWxkYClcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIHR4SGV4OlxuICAgICAgICAgICAgJ2lhUmhjbU4yeENCZm5NZ1l0YnlHNFJMMURzcFloeFFleW45UXJKK3MyWmNEVGN4Syt5T0grS05tWldYTkEraWlabmJPQTJ0bEpLTm5aVzZzZEdWemRHNWxkQzEyTVM0d29tZG94Q0JJWTdVWXBMUElUc2dROGkxUEVJSExEM0h3V2Flc0lON0dMMzl3NVFrNklxSnNkczREYTJrTW8zTnVaTVFnWDV6SUdMVzhodUVTOVE3S1dJY1VIc3AvVUt5ZnJObVhBMDNNU3ZzamgvaWtkSGx3WmFWaGVHWmxjcVI0WVdsa3pnbXBPa1k9JyxcbiAgICAgICAgICB0eEhhc2g6ICdBUllNT1hNS1pXTTM3MkpCRkJUQURaTkpaVTdTNUhLNDROWkRaTFZYNVVSNVVQSVdUN0ZBJyxcbiAgICAgICAgICB0eEluZm86IHtcbiAgICAgICAgICAgIGlkOiAnQVJZTU9YTUtaV00zNzJKQkZCVEFEWk5KWlU3UzVISzQ0TlpEWkxWWDVVUjVVUElXVDdGQScsXG4gICAgICAgICAgICB0eXBlOiAnYXhmZXInLFxuICAgICAgICAgICAgZnJvbTogJ0w2T01RR0ZWWFNET0NFWFZCM0ZGUkJZVUQzRkg2VUZNVDZXTlRGWURKWEdFVjZaRFE3NEVYR0Y2QkUnLFxuICAgICAgICAgICAgZmVlOiAxMDAwLFxuICAgICAgICAgICAgZmlyc3RSb3VuZDogNTczNjk4OTIsXG4gICAgICAgICAgICBsYXN0Um91bmQ6IDU3MzcwODkyLFxuICAgICAgICAgICAgbm90ZToge30sXG4gICAgICAgICAgICB0b2tlbklkOiAxNjIwODU0NDYsXG4gICAgICAgICAgICBnZW5lc2lzSUQ6ICd0ZXN0bmV0LXYxLjAnLFxuICAgICAgICAgICAgZ2VuZXNpc0hhc2g6ICdTR08xR0tTenlFN0lFUEl0VHhDQnl3OXg4Rm1uckNEZXhpOS9jT1VKT2lJPScsXG4gICAgICAgICAgICB0bzogJ0w2T01RR0ZWWFNET0NFWFZCM0ZGUkJZVUQzRkg2VUZNVDZXTlRGWURKWEdFVjZaRFE3NEVYR0Y2QkUnLFxuICAgICAgICAgICAgYW1vdW50OiAnMCcsXG4gICAgICAgICAgICB0eFR5cGU6ICdlbmFibGVUb2tlbicsXG4gICAgICAgICAgICB0b2tlbk5hbWU6ICdUQUxHTycsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBmZWVJbmZvOiB7XG4gICAgICAgICAgICBzaXplOiAyNTEsXG4gICAgICAgICAgICBmZWU6IDEwMDAsXG4gICAgICAgICAgICBmZWVSYXRlOiA0LFxuICAgICAgICAgICAgZmVlU3RyaW5nOiAnMTAwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBrZXlzOiBbXG4gICAgICAgICAgICAnNDJNSVlMMktCSVNWNldKUkFMVFRTWEhCRUdMTkY3TU1RNzRGR1NZVUNUNVlQM1YyS0VOSkdSRlZWUScsXG4gICAgICAgICAgICAnTUFHWFpUREZXNVFFWFVLT1VESUdIVFhPS0RXN1ROUUVETFdQQkVaRUwzVkZVM1lBQTJQR1lSUzY1TScsXG4gICAgICAgICAgICAnVE1FSlRJN1hOQ0FDREczQlRPRElOVzZDTVI2QVJZSUtUQ0ZQQTJHTUlYTDRYNVE0QkNFNlZITVdBTScsXG4gICAgICAgICAgXSxcbiAgICAgICAgICBhZGRyZXNzVmVyc2lvbjogMSxcbiAgICAgICAgICBjb2luOiAndGFsZ28nLFxuICAgICAgICB9KTtcbiAgICAgIGNvbnN0IHZhbGlkYXRlUHdkU3R1YiA9IHN0dWIod2FsbGV0LCAnZ2V0S2V5Y2hhaW5zQW5kVmFsaWRhdGVQYXNzcGhyYXNlJyBhcyBrZXlvZiBXYWxsZXQpLnJlc29sdmVzKFtdKTtcbiAgICAgIGNvbnN0IHNpZ25UeFN0dWIgPSBzdHViKHdhbGxldCwgJ3NpZ25UcmFuc2FjdGlvbicpLnJlc29sdmVzKHt9KTtcblxuICAgICAgYXdhaXQgd2FsbGV0LnNlbmRUb2tlbkVuYWJsZW1lbnRzKHtcbiAgICAgICAgdmVyaWZpY2F0aW9uOiB7IHZlcmlmeVRva2VuRW5hYmxlbWVudDogdHJ1ZSB9LFxuICAgICAgICBlbmFibGVUb2tlbnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiAndGFsZ286SlBULTE2MjA4NTQ0NicsXG4gICAgICAgICAgICBhZGRyZXNzOiAnTDZPTVFHRlZYU0RPQ0VYVkIzRkZSQllVRDNGSDZVRk1UNldOVEZZREpYR0VWNlpEUTc0RVhHRjZCRScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuXG4gICAgICB2ZXJpZnlUcmFuc2FjdGlvblN0dWIuY2FsbGVkLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICB2ZXJpZnlUcmFuc2FjdGlvblN0dWIucmVzdG9yZSgpO1xuICAgICAgdmFsaWRhdGVQd2RTdHViLnJlc3RvcmUoKTtcbiAgICAgIHNpZ25UeFN0dWIucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIGludmFsaWQgdG9rZW4gZW5hYmxlbWVudCB0cmFuc2FjdGlvbiBpcyByZXR1cm5lZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHZlcmlmeVRyYW5zYWN0aW9uU3R1YiA9IHNweShiYXNlY29pbiwgJ3ZlcmlmeVRyYW5zYWN0aW9uJyk7XG4gICAgICBub2NrKGJnVXJsKVxuICAgICAgICAucG9zdChgL2FwaS92Mi90YWxnby93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdHgvYnVpbGRgKVxuICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgdHhIZXg6XG4gICAgICAgICAgICAnaWFSaGNtTjJ4Q0Jmbk1nWXRieUc0UkwxRHNwWWh4UWV5bjlRckorczJaY0RUY3hLK3lPSCtLTm1aV1hOQStpaVpuYk9BMnRwZXFOblpXNnNkR1Z6ZEc1bGRDMTJNUzR3b21kb3hDQklZN1VZcExQSVRzZ1E4aTFQRUlITEQzSHdXYWVzSU43R0wzOXc1UWs2SXFKc2RzNERhMjFpbzNOdVpNUWdYNXpJR0xXOGh1RVM5UTdLV0ljVUhzcC9VS3lmck5tWEEwM01TdnNqaC9pa2RIbHdaYVZoZUdabGNxUjRZV2xremdBQ3dOOD0nLFxuICAgICAgICAgIHR4SGFzaDogJ1lQUUdZTkJPQ1BYTUJGVEJaSDJBUUdDRFozQzI3NjJUNkVZUVk0NkY3TFJHMlVSWDZETEEnLFxuICAgICAgICAgIHR4SW5mbzoge1xuICAgICAgICAgICAgaWQ6ICdZUFFHWU5CT0NQWE1CRlRCWkgyQVFHQ0RaM0MyNzYyVDZFWVFZNDZGN0xSRzJVUlg2RExBJyxcbiAgICAgICAgICAgIHR5cGU6ICdheGZlcicsXG4gICAgICAgICAgICBmcm9tOiAnTDZPTVFHRlZYU0RPQ0VYVkIzRkZSQllVRDNGSDZVRk1UNldOVEZZREpYR0VWNlpEUTc0RVhHRjZCRScsXG4gICAgICAgICAgICBmZWU6IDEwMDAsXG4gICAgICAgICAgICBmaXJzdFJvdW5kOiA1NzM3MTAwMixcbiAgICAgICAgICAgIGxhc3RSb3VuZDogNTczNzIwMDIsXG4gICAgICAgICAgICBub3RlOiB7fSxcbiAgICAgICAgICAgIHRva2VuSWQ6IDE4MDQ0NyxcbiAgICAgICAgICAgIGdlbmVzaXNJRDogJ3Rlc3RuZXQtdjEuMCcsXG4gICAgICAgICAgICBnZW5lc2lzSGFzaDogJ1NHTzFHS1N6eUU3SUVQSXRUeENCeXc5eDhGbW5yQ0RleGk5L2NPVUpPaUk9JyxcbiAgICAgICAgICAgIHRvOiAnTDZPTVFHRlZYU0RPQ0VYVkIzRkZSQllVRDNGSDZVRk1UNldOVEZZREpYR0VWNlpEUTc0RVhHRjZCRScsXG4gICAgICAgICAgICBhbW91bnQ6ICcwJyxcbiAgICAgICAgICAgIHR4VHlwZTogJ2VuYWJsZVRva2VuJyxcbiAgICAgICAgICAgIHRva2VuTmFtZTogJ1RBTEdPJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGZlZUluZm86IHtcbiAgICAgICAgICAgIHNpemU6IDI1MSxcbiAgICAgICAgICAgIGZlZTogMTAwMCxcbiAgICAgICAgICAgIGZlZVJhdGU6IDQsXG4gICAgICAgICAgICBmZWVTdHJpbmc6ICcxMDAwJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGtleXM6IFtcbiAgICAgICAgICAgICc0Mk1JWUwyS0JJU1Y2V0pSQUxUVFNYSEJFR0xORjdNTVE3NEZHU1lVQ1Q1WVAzVjJLRU5KR1JGVlZRJyxcbiAgICAgICAgICAgICdNQUdYWlRERlc1UUVYVUtPVURJR0hUWE9LRFc3VE5RRURMV1BCRVpFTDNWRlUzWUFBMlBHWVJTNjVNJyxcbiAgICAgICAgICAgICdUTUVKVEk3WE5DQUNERzNCVE9ESU5XNkNNUjZBUllJS1RDRlBBMkdNSVhMNFg1UTRCQ0U2VkhNV0FNJyxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGFkZHJlc3NWZXJzaW9uOiAxLFxuICAgICAgICAgIGNvaW46ICd0YWxnbycsXG4gICAgICAgIH0pO1xuICAgICAgc3R1Yih3YWxsZXQsICdnZXRLZXljaGFpbnNBbmRWYWxpZGF0ZVBhc3NwaHJhc2UnIGFzIGtleW9mIFdhbGxldCkucmVzb2x2ZXMoW10pO1xuICAgICAgc3R1Yih3YWxsZXQsICdzaWduVHJhbnNhY3Rpb24nKS5yZXNvbHZlcyh7fSk7XG5cbiAgICAgIGNvbnN0IHsgc3VjY2VzcywgZmFpbHVyZSB9ID0gYXdhaXQgd2FsbGV0LnNlbmRUb2tlbkVuYWJsZW1lbnRzKHtcbiAgICAgICAgdmVyaWZpY2F0aW9uOiB7IHZlcmlmeVRva2VuRW5hYmxlbWVudDogdHJ1ZSB9LFxuICAgICAgICBlbmFibGVUb2tlbnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiAndGFsZ286SlBULTE2MjA4NTQ0NicsXG4gICAgICAgICAgICBhZGRyZXNzOiAnTDZPTVFHRlZYU0RPQ0VYVkIzRkZSQllVRDNGSDZVRk1UNldOVEZZREpYR0VWNlpEUTc0RVhHRjZCRScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuXG4gICAgICB2ZXJpZnlUcmFuc2FjdGlvblN0dWIuY2FsbGVkLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICBzdWNjZXNzLmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG4gICAgICBmYWlsdXJlLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBmYWlsdXJlWzBdLm1lc3NhZ2Uuc2hvdWxkLmVxdWFsKFxuICAgICAgICAnVG9rZW4gZW5hYmxlbWVudCB2ZXJpZmljYXRpb24gZmFpbGVkOiBleHBlY3RlZCB0b2tlbiBJRCAxNjIwODU0NDYgYnV0IHRyYW5zYWN0aW9uIGhhcyB0b2tlbiBJRCAxODA0NDcnXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|