@bitgo-beta/sdk-coin-trx 1.2.3-alpha.402 → 1.2.3-alpha.404
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +22 -0
- package/dist/src/lib/address.d.ts +11 -0
- package/dist/src/lib/address.d.ts.map +1 -0
- package/dist/src/lib/address.js +13 -0
- package/dist/src/lib/builder.d.ts +3 -0
- package/dist/src/lib/builder.d.ts.map +1 -0
- package/dist/src/lib/builder.js +10 -0
- package/dist/src/lib/constants.d.ts +3 -0
- package/dist/src/lib/constants.d.ts.map +1 -0
- package/dist/src/lib/constants.js +6 -0
- package/dist/src/lib/contractCallBuilder.d.ts +62 -0
- package/dist/src/lib/contractCallBuilder.d.ts.map +1 -0
- package/dist/src/lib/contractCallBuilder.js +218 -0
- package/dist/src/lib/delegateResourceTxBuilder.d.ts +27 -0
- package/dist/src/lib/delegateResourceTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/delegateResourceTxBuilder.js +98 -0
- package/dist/src/lib/enum.d.ts +58 -0
- package/dist/src/lib/enum.d.ts.map +1 -0
- package/dist/src/lib/enum.js +64 -0
- package/dist/src/lib/freezeBalanceTxBuilder.d.ts +71 -0
- package/dist/src/lib/freezeBalanceTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/freezeBalanceTxBuilder.js +211 -0
- package/dist/src/lib/iface.d.ts +321 -0
- package/dist/src/lib/iface.d.ts.map +1 -0
- package/dist/src/lib/iface.js +3 -0
- package/dist/src/lib/index.d.ts +12 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +53 -0
- package/dist/src/lib/keyPair.d.ts +43 -0
- package/dist/src/lib/keyPair.d.ts.map +1 -0
- package/dist/src/lib/keyPair.js +134 -0
- package/dist/src/lib/resourceManagementTxBuilder.d.ts +72 -0
- package/dist/src/lib/resourceManagementTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/resourceManagementTxBuilder.js +150 -0
- package/dist/src/lib/tokenTransferBuilder.d.ts +23 -0
- package/dist/src/lib/tokenTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/tokenTransferBuilder.js +42 -0
- package/dist/src/lib/transaction.d.ts +74 -0
- package/dist/src/lib/transaction.d.ts.map +1 -0
- package/dist/src/lib/transaction.js +312 -0
- package/dist/src/lib/transactionBuilder.d.ts +110 -0
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
- package/dist/src/lib/transactionBuilder.js +304 -0
- package/dist/src/lib/undelegateResourceTxBuilder.d.ts +27 -0
- package/dist/src/lib/undelegateResourceTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/undelegateResourceTxBuilder.js +98 -0
- package/dist/src/lib/unfreezeBalanceTxBuilder.d.ts +65 -0
- package/dist/src/lib/unfreezeBalanceTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/unfreezeBalanceTxBuilder.js +204 -0
- package/dist/src/lib/utils.d.ts +225 -0
- package/dist/src/lib/utils.d.ts.map +1 -0
- package/dist/src/lib/utils.js +824 -0
- package/dist/src/lib/voteWitnessTxBuilder.d.ts +62 -0
- package/dist/src/lib/voteWitnessTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/voteWitnessTxBuilder.js +219 -0
- package/dist/src/lib/withdrawBuilder.d.ts +49 -0
- package/dist/src/lib/withdrawBuilder.d.ts.map +1 -0
- package/dist/src/lib/withdrawBuilder.js +167 -0
- package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.d.ts +49 -0
- package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.js +167 -0
- package/dist/src/lib/wrappedBuilder.d.ts +110 -0
- package/dist/src/lib/wrappedBuilder.d.ts.map +1 -0
- package/dist/src/lib/wrappedBuilder.js +192 -0
- package/dist/src/register.d.ts +3 -0
- package/dist/src/register.d.ts.map +1 -0
- package/dist/src/register.js +15 -0
- package/dist/src/trx.d.ts +266 -0
- package/dist/src/trx.d.ts.map +1 -0
- package/dist/src/trx.js +788 -0
- package/dist/src/trxToken.d.ts +38 -0
- package/dist/src/trxToken.d.ts.map +1 -0
- package/dist/src/trxToken.js +91 -0
- package/dist/src/ttrx.d.ts +13 -0
- package/dist/src/ttrx.d.ts.map +1 -0
- package/dist/src/ttrx.js +14 -0
- package/dist/test/fixtures.d.ts +40 -0
- package/dist/test/fixtures.d.ts.map +1 -0
- package/dist/test/fixtures.js +46 -0
- package/dist/test/resources.d.ts +586 -0
- package/dist/test/resources.d.ts.map +1 -0
- package/dist/test/resources.js +746 -0
- package/dist/test/unit/index.d.ts +2 -0
- package/dist/test/unit/index.d.ts.map +1 -0
- package/dist/test/unit/index.js +19 -0
- package/dist/test/unit/keyPair.d.ts +2 -0
- package/dist/test/unit/keyPair.d.ts.map +1 -0
- package/dist/test/unit/keyPair.js +163 -0
- package/dist/test/unit/transaction.d.ts +2 -0
- package/dist/test/unit/transaction.d.ts.map +1 -0
- package/dist/test/unit/transaction.js +38 -0
- package/dist/test/unit/transactionBuilder/contractCallBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/contractCallBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/contractCallBuilder.js +315 -0
- package/dist/test/unit/transactionBuilder/delegateResourceTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/delegateResourceTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/delegateResourceTxBuilder.js +255 -0
- package/dist/test/unit/transactionBuilder/freezeBalanceTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/freezeBalanceTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/freezeBalanceTxBuilder.js +256 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.js +42 -0
- package/dist/test/unit/transactionBuilder/undelegateResourceTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/undelegateResourceTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/undelegateResourceTxBuilder.js +255 -0
- package/dist/test/unit/transactionBuilder/unfreezeBalanceTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/unfreezeBalanceTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/unfreezeBalanceTxBuilder.js +256 -0
- package/dist/test/unit/transactionBuilder/voteWitnessTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/voteWitnessTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/voteWitnessTxBuilder.js +277 -0
- package/dist/test/unit/transactionBuilder/withdrawBalanceBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/withdrawBalanceBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/withdrawBalanceBuilder.js +213 -0
- package/dist/test/unit/transactionBuilder/withdrawExpireUnfreezeTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/withdrawExpireUnfreezeTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/withdrawExpireUnfreezeTxBuilder.js +213 -0
- package/dist/test/unit/transactionBuilder/wrappedBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/wrappedBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/wrappedBuilder.js +50 -0
- package/dist/test/unit/transactionBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder.js +178 -0
- package/dist/test/unit/trx.d.ts +2 -0
- package/dist/test/unit/trx.d.ts.map +1 -0
- package/dist/test/unit/trx.js +532 -0
- package/dist/test/unit/util.d.ts +2 -0
- package/dist/test/unit/util.d.ts.map +1 -0
- package/dist/test/unit/util.js +141 -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 +378 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +10 -7
- package/.eslintignore +0 -5
- package/.mocharc.yml +0 -8
- package/CHANGELOG.md +0 -1092
- package/resources/README.md +0 -31
- package/resources/protobuf/Contract.proto +0 -288
- package/resources/protobuf/Discover.proto +0 -44
- package/resources/protobuf/tron.d.ts +0 -12469
- package/resources/protobuf/tron.js +0 -37192
- package/resources/protobuf/tron.proto +0 -683
|
@@ -0,0 +1,824 @@
|
|
|
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
|
+
exports.VALID_RESOURCE_TYPES = exports.tokenTestnetContractAddresses = exports.tokenMainnetContractAddresses = exports.TRANSACTION_DEFAULT_EXPIRATION = exports.TRANSACTION_MAX_EXPIRATION = void 0;
|
|
40
|
+
exports.isBase58Address = isBase58Address;
|
|
41
|
+
exports.getByteArrayFromHexAddress = getByteArrayFromHexAddress;
|
|
42
|
+
exports.getHexAddressFromByteArray = getHexAddressFromByteArray;
|
|
43
|
+
exports.verifySignature = verifySignature;
|
|
44
|
+
exports.getHexAddressFromBase58Address = getHexAddressFromBase58Address;
|
|
45
|
+
exports.getPubKeyFromPriKey = getPubKeyFromPriKey;
|
|
46
|
+
exports.getAddressFromPriKey = getAddressFromPriKey;
|
|
47
|
+
exports.getBase58AddressFromByteArray = getBase58AddressFromByteArray;
|
|
48
|
+
exports.getBase58AddressFromHex = getBase58AddressFromHex;
|
|
49
|
+
exports.signTransaction = signTransaction;
|
|
50
|
+
exports.signString = signString;
|
|
51
|
+
exports.getRawAddressFromPubKey = getRawAddressFromPubKey;
|
|
52
|
+
exports.decodeTransaction = decodeTransaction;
|
|
53
|
+
exports.decodeRawTransaction = decodeRawTransaction;
|
|
54
|
+
exports.getHexFromBase64 = getHexFromBase64;
|
|
55
|
+
exports.isValidHex = isValidHex;
|
|
56
|
+
exports.decodeTransferContract = decodeTransferContract;
|
|
57
|
+
exports.decodeTriggerSmartContract = decodeTriggerSmartContract;
|
|
58
|
+
exports.decodeAccountPermissionUpdateContract = decodeAccountPermissionUpdateContract;
|
|
59
|
+
exports.decodeFreezeBalanceV2Contract = decodeFreezeBalanceV2Contract;
|
|
60
|
+
exports.decodeVoteWitnessContract = decodeVoteWitnessContract;
|
|
61
|
+
exports.decodeUnfreezeBalanceV2Contract = decodeUnfreezeBalanceV2Contract;
|
|
62
|
+
exports.decodeWithdrawBalanceContract = decodeWithdrawBalanceContract;
|
|
63
|
+
exports.decodeWithdrawExpireUnfreezeContract = decodeWithdrawExpireUnfreezeContract;
|
|
64
|
+
exports.decodeDelegateResourceContract = decodeDelegateResourceContract;
|
|
65
|
+
exports.decodeUnDelegateResourceContract = decodeUnDelegateResourceContract;
|
|
66
|
+
exports.isValidTxJsonString = isValidTxJsonString;
|
|
67
|
+
exports.isValidRawTransactionFormat = isValidRawTransactionFormat;
|
|
68
|
+
exports.toHex = toHex;
|
|
69
|
+
exports.encodeDataParams = encodeDataParams;
|
|
70
|
+
exports.decodeDataParams = decodeDataParams;
|
|
71
|
+
exports.generateRawDataHex = generateRawDataHex;
|
|
72
|
+
const assert_1 = __importDefault(require("assert"));
|
|
73
|
+
const hex = __importStar(require("@stablelib/hex"));
|
|
74
|
+
const tronweb = __importStar(require("tronweb"));
|
|
75
|
+
const tron_1 = require("../../resources/protobuf/tron");
|
|
76
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
77
|
+
const statics_1 = require("@bitgo-beta/statics");
|
|
78
|
+
const enum_1 = require("./enum");
|
|
79
|
+
const utils_1 = require("ethers/lib/utils");
|
|
80
|
+
const constants_1 = require("./constants");
|
|
81
|
+
exports.TRANSACTION_MAX_EXPIRATION = 86400000; // one day
|
|
82
|
+
exports.TRANSACTION_DEFAULT_EXPIRATION = 3600000; // one hour
|
|
83
|
+
const ADDRESS_PREFIX_REGEX = /^(41)/;
|
|
84
|
+
const ADDRESS_PREFIX = '41';
|
|
85
|
+
const getTronTokens = (network = 'mainnet') => {
|
|
86
|
+
return statics_1.coins
|
|
87
|
+
.filter((coin) => coin.family === 'trx')
|
|
88
|
+
.filter((trx) => trx.network.type === network && trx.isToken).map((coins) => coins.contractAddress.toString());
|
|
89
|
+
};
|
|
90
|
+
exports.tokenMainnetContractAddresses = getTronTokens('mainnet');
|
|
91
|
+
exports.tokenTestnetContractAddresses = getTronTokens('testnet');
|
|
92
|
+
exports.VALID_RESOURCE_TYPES = ['ENERGY', 'BANDWIDTH'];
|
|
93
|
+
/**
|
|
94
|
+
* @param address
|
|
95
|
+
*/
|
|
96
|
+
function isBase58Address(address) {
|
|
97
|
+
return tronweb.utils.crypto.isAddressValid(address);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* @param str
|
|
101
|
+
*/
|
|
102
|
+
function getByteArrayFromHexAddress(str) {
|
|
103
|
+
return tronweb.utils.code.hexStr2byteArray(str.replace('0x', ''));
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* @param arr
|
|
107
|
+
*/
|
|
108
|
+
function getHexAddressFromByteArray(arr) {
|
|
109
|
+
return tronweb.utils.code.byteArray2hexStr(arr);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* @param messageToVerify
|
|
113
|
+
* @param base58Address
|
|
114
|
+
* @param sigHex
|
|
115
|
+
* @param useTronHeader
|
|
116
|
+
*/
|
|
117
|
+
function verifySignature(messageToVerify, base58Address, sigHex, useTronHeader = true) {
|
|
118
|
+
if (!isValidHex(sigHex)) {
|
|
119
|
+
throw new sdk_core_1.UtilsError('signature is not in a valid format, needs to be hexadecimal');
|
|
120
|
+
}
|
|
121
|
+
if (!isValidHex(messageToVerify)) {
|
|
122
|
+
throw new sdk_core_1.UtilsError('message is not in a valid format, needs to be hexadecimal');
|
|
123
|
+
}
|
|
124
|
+
if (!isBase58Address(base58Address)) {
|
|
125
|
+
throw new sdk_core_1.UtilsError('address needs to be base58 encoded');
|
|
126
|
+
}
|
|
127
|
+
return tronweb.Trx.verifySignature(messageToVerify, base58Address, sigHex, useTronHeader);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* @param base58
|
|
131
|
+
*/
|
|
132
|
+
function getHexAddressFromBase58Address(base58) {
|
|
133
|
+
// pulled from: https://github.com/TRON-US/tronweb/blob/dcb8efa36a5ebb65c4dab3626e90256a453f3b0d/src/utils/help.js#L17
|
|
134
|
+
// but they don't surface this call in index.js
|
|
135
|
+
const bytes = tronweb.utils.crypto.decodeBase58Address(base58);
|
|
136
|
+
// Ensure bytes is a ByteArray (number[])
|
|
137
|
+
if (Array.isArray(bytes)) {
|
|
138
|
+
return getHexAddressFromByteArray(bytes);
|
|
139
|
+
}
|
|
140
|
+
throw new sdk_core_1.UtilsError('Failed to decode base58 address to byte array');
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* @param privateKey
|
|
144
|
+
*/
|
|
145
|
+
function getPubKeyFromPriKey(privateKey) {
|
|
146
|
+
return tronweb.utils.crypto.getPubKeyFromPriKey(privateKey);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* @param privateKey
|
|
150
|
+
*/
|
|
151
|
+
function getAddressFromPriKey(privateKey) {
|
|
152
|
+
return tronweb.utils.crypto.getAddressFromPriKey(privateKey);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* @param address
|
|
156
|
+
*/
|
|
157
|
+
function getBase58AddressFromByteArray(address) {
|
|
158
|
+
return tronweb.utils.crypto.getBase58CheckAddress(address);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* @param hex
|
|
162
|
+
*/
|
|
163
|
+
function getBase58AddressFromHex(hex) {
|
|
164
|
+
const arr = getByteArrayFromHexAddress(hex);
|
|
165
|
+
return getBase58AddressFromByteArray(arr);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* @param privateKey
|
|
169
|
+
* @param transaction
|
|
170
|
+
*/
|
|
171
|
+
function signTransaction(privateKey, transaction) {
|
|
172
|
+
return tronweb.utils.crypto.signTransaction(privateKey, transaction);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* @param message
|
|
176
|
+
* @param privateKey
|
|
177
|
+
* @param useTronHeader
|
|
178
|
+
*/
|
|
179
|
+
function signString(message, privateKey, useTronHeader = true) {
|
|
180
|
+
return tronweb.Trx.signString(message, privateKey, useTronHeader);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* @param pubBytes
|
|
184
|
+
*/
|
|
185
|
+
function getRawAddressFromPubKey(pubBytes) {
|
|
186
|
+
return tronweb.utils.crypto.computeAddress(pubBytes);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Decodes a hex encoded transaction in its protobuf representation.
|
|
190
|
+
*
|
|
191
|
+
* @param hexString raw_data_hex field from tron transactions
|
|
192
|
+
*/
|
|
193
|
+
function decodeTransaction(hexString) {
|
|
194
|
+
const rawTransaction = decodeRawTransaction(hexString);
|
|
195
|
+
// there should not be multiple contracts in this data
|
|
196
|
+
if (rawTransaction.contracts.length !== 1) {
|
|
197
|
+
throw new sdk_core_1.UtilsError('Number of contracts is greater than 1.');
|
|
198
|
+
}
|
|
199
|
+
let contract;
|
|
200
|
+
let contractType;
|
|
201
|
+
// ensure the contract type is supported
|
|
202
|
+
switch (rawTransaction.contracts[0].parameter.type_url) {
|
|
203
|
+
case 'type.googleapis.com/protocol.TransferContract':
|
|
204
|
+
contractType = enum_1.ContractType.Transfer;
|
|
205
|
+
contract = exports.decodeTransferContract(rawTransaction.contracts[0].parameter.value);
|
|
206
|
+
break;
|
|
207
|
+
case 'type.googleapis.com/protocol.AccountPermissionUpdateContract':
|
|
208
|
+
contractType = enum_1.ContractType.AccountPermissionUpdate;
|
|
209
|
+
contract = exports.decodeAccountPermissionUpdateContract(rawTransaction.contracts[0].parameter.value);
|
|
210
|
+
break;
|
|
211
|
+
case 'type.googleapis.com/protocol.TriggerSmartContract':
|
|
212
|
+
contractType = enum_1.ContractType.TriggerSmartContract;
|
|
213
|
+
contract = exports.decodeTriggerSmartContract(rawTransaction.contracts[0].parameter.value);
|
|
214
|
+
break;
|
|
215
|
+
case 'type.googleapis.com/protocol.FreezeBalanceV2Contract':
|
|
216
|
+
contractType = enum_1.ContractType.FreezeBalanceV2;
|
|
217
|
+
contract = decodeFreezeBalanceV2Contract(rawTransaction.contracts[0].parameter.value);
|
|
218
|
+
break;
|
|
219
|
+
case 'type.googleapis.com/protocol.VoteWitnessContract':
|
|
220
|
+
contractType = enum_1.ContractType.VoteWitness;
|
|
221
|
+
contract = decodeVoteWitnessContract(rawTransaction.contracts[0].parameter.value);
|
|
222
|
+
break;
|
|
223
|
+
case 'type.googleapis.com/protocol.WithdrawExpireUnfreezeContract':
|
|
224
|
+
contract = decodeWithdrawExpireUnfreezeContract(rawTransaction.contracts[0].parameter.value);
|
|
225
|
+
contractType = enum_1.ContractType.WithdrawExpireUnfreeze;
|
|
226
|
+
break;
|
|
227
|
+
case 'type.googleapis.com/protocol.WithdrawBalanceContract':
|
|
228
|
+
contract = decodeWithdrawBalanceContract(rawTransaction.contracts[0].parameter.value);
|
|
229
|
+
contractType = enum_1.ContractType.WithdrawBalance;
|
|
230
|
+
break;
|
|
231
|
+
case 'type.googleapis.com/protocol.UnfreezeBalanceV2Contract':
|
|
232
|
+
contract = decodeUnfreezeBalanceV2Contract(rawTransaction.contracts[0].parameter.value);
|
|
233
|
+
contractType = enum_1.ContractType.UnfreezeBalanceV2;
|
|
234
|
+
break;
|
|
235
|
+
case constants_1.DELEGATION_TYPE_URL:
|
|
236
|
+
contractType = enum_1.ContractType.DelegateResourceContract;
|
|
237
|
+
contract = decodeDelegateResourceContract(rawTransaction.contracts[0].parameter.value);
|
|
238
|
+
break;
|
|
239
|
+
case 'type.googleapis.com/protocol.UnDelegateResourceContract':
|
|
240
|
+
contractType = enum_1.ContractType.UnDelegateResourceContract;
|
|
241
|
+
contract = decodeUnDelegateResourceContract(rawTransaction.contracts[0].parameter.value);
|
|
242
|
+
break;
|
|
243
|
+
default:
|
|
244
|
+
throw new sdk_core_1.UtilsError('Unsupported contract type');
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
contractType,
|
|
248
|
+
contract,
|
|
249
|
+
expiration: rawTransaction.expiration,
|
|
250
|
+
timestamp: rawTransaction.timestamp,
|
|
251
|
+
ref_block_bytes: rawTransaction.blockBytes,
|
|
252
|
+
ref_block_hash: rawTransaction.blockHash,
|
|
253
|
+
fee_limit: +rawTransaction.feeLimit,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Decodes a transaction's raw field from a base64 encoded string. This is a protobuf representation.
|
|
258
|
+
*
|
|
259
|
+
* @param hexString this is the raw hexadecimal encoded string. Doc found in the following link.
|
|
260
|
+
* @example
|
|
261
|
+
* @see {@link https://github.com/BitGo/bitgo-account-lib/blob/5f282588701778a4421c75fa61f42713f56e95b9/resources/protobuf/tron.proto#L319}
|
|
262
|
+
*/
|
|
263
|
+
function decodeRawTransaction(hexString) {
|
|
264
|
+
const bytes = Buffer.from(hexString, 'hex');
|
|
265
|
+
let raw;
|
|
266
|
+
try {
|
|
267
|
+
// we need to decode our raw_data_hex field first
|
|
268
|
+
raw = tron_1.protocol.Transaction.raw.decode(bytes);
|
|
269
|
+
}
|
|
270
|
+
catch (e) {
|
|
271
|
+
throw new sdk_core_1.UtilsError('There was an error decoding the initial raw_data_hex from the serialized tx.');
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
expiration: Number(raw.expiration),
|
|
275
|
+
timestamp: Number(raw.timestamp),
|
|
276
|
+
contracts: raw.contract,
|
|
277
|
+
blockBytes: toHex(raw.refBlockBytes),
|
|
278
|
+
feeLimit: raw.feeLimit,
|
|
279
|
+
blockHash: toHex(raw.refBlockHash),
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Converts a base64 encoded string to hex
|
|
284
|
+
*
|
|
285
|
+
* @param base64 - The base64 encoded string to convert
|
|
286
|
+
* @returns {string} - The hex representation
|
|
287
|
+
*/
|
|
288
|
+
function getHexFromBase64(base64) {
|
|
289
|
+
const buffer = Buffer.from(base64, 'base64');
|
|
290
|
+
return buffer.toString('hex');
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Indicates whether the passed string is a safe hex string for tron's purposes.
|
|
294
|
+
*
|
|
295
|
+
* @param hex A valid hex string must be a string made of numbers and characters and has an even length.
|
|
296
|
+
*/
|
|
297
|
+
function isValidHex(hex) {
|
|
298
|
+
return /^(0x)?([0-9a-f]{2})+$/i.test(hex);
|
|
299
|
+
}
|
|
300
|
+
/** Deserialize the segment of the txHex which corresponds with the details of the transfer
|
|
301
|
+
*
|
|
302
|
+
* @param transferHex is the value property of the "parameter" field of contractList[0]
|
|
303
|
+
* */
|
|
304
|
+
function decodeTransferContract(transferHex) {
|
|
305
|
+
const contractBytes = Buffer.from(transferHex, 'base64');
|
|
306
|
+
let transferContract;
|
|
307
|
+
try {
|
|
308
|
+
transferContract = tron_1.protocol.TransferContract.decode(contractBytes);
|
|
309
|
+
}
|
|
310
|
+
catch (e) {
|
|
311
|
+
throw new sdk_core_1.UtilsError('There was an error decoding the transfer contract in the transaction.');
|
|
312
|
+
}
|
|
313
|
+
if (!transferContract.ownerAddress) {
|
|
314
|
+
throw new sdk_core_1.UtilsError('Owner address does not exist in this transfer contract.');
|
|
315
|
+
}
|
|
316
|
+
if (!transferContract.toAddress) {
|
|
317
|
+
throw new sdk_core_1.UtilsError('Destination address does not exist in this transfer contract.');
|
|
318
|
+
}
|
|
319
|
+
if (!transferContract.hasOwnProperty('amount')) {
|
|
320
|
+
throw new sdk_core_1.UtilsError('Amount does not exist in this transfer contract.');
|
|
321
|
+
}
|
|
322
|
+
// deserialize attributes
|
|
323
|
+
const owner_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(transferContract.ownerAddress, 'base64').toString('hex')));
|
|
324
|
+
const to_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(transferContract.toAddress, 'base64').toString('hex')));
|
|
325
|
+
const amount = transferContract.amount;
|
|
326
|
+
return [
|
|
327
|
+
{
|
|
328
|
+
parameter: {
|
|
329
|
+
value: {
|
|
330
|
+
amount: Number(amount),
|
|
331
|
+
owner_address,
|
|
332
|
+
to_address,
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
];
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Deserialize the segment of the txHex corresponding with trigger smart contract
|
|
340
|
+
*
|
|
341
|
+
* @param {string} base64
|
|
342
|
+
* @returns {AccountPermissionUpdateContract}
|
|
343
|
+
*/
|
|
344
|
+
function decodeTriggerSmartContract(base64) {
|
|
345
|
+
let contractCallDecoded;
|
|
346
|
+
try {
|
|
347
|
+
contractCallDecoded = tron_1.protocol.TriggerSmartContract.decode(Buffer.from(base64, 'base64')).toJSON();
|
|
348
|
+
}
|
|
349
|
+
catch (e) {
|
|
350
|
+
throw new sdk_core_1.UtilsError('There was an error decoding the contract call in the transaction.');
|
|
351
|
+
}
|
|
352
|
+
if (!contractCallDecoded.ownerAddress) {
|
|
353
|
+
throw new sdk_core_1.UtilsError('Owner address does not exist in this contract call.');
|
|
354
|
+
}
|
|
355
|
+
if (!contractCallDecoded.contractAddress) {
|
|
356
|
+
throw new sdk_core_1.UtilsError('Destination contract address does not exist in this contract call.');
|
|
357
|
+
}
|
|
358
|
+
if (!contractCallDecoded.data) {
|
|
359
|
+
throw new sdk_core_1.UtilsError('Data does not exist in this contract call.');
|
|
360
|
+
}
|
|
361
|
+
// deserialize attributes
|
|
362
|
+
const owner_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(contractCallDecoded.ownerAddress, 'base64').toString('hex')));
|
|
363
|
+
const contract_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(contractCallDecoded.contractAddress, 'base64').toString('hex')));
|
|
364
|
+
const data = contractCallDecoded.data;
|
|
365
|
+
return [
|
|
366
|
+
{
|
|
367
|
+
parameter: {
|
|
368
|
+
value: {
|
|
369
|
+
data: data,
|
|
370
|
+
owner_address,
|
|
371
|
+
contract_address,
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
];
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Deserialize the segment of the txHex corresponding with the details of the contract which updates
|
|
379
|
+
* account permission
|
|
380
|
+
*
|
|
381
|
+
* @param {string} base64
|
|
382
|
+
* @returns {AccountPermissionUpdateContract}
|
|
383
|
+
*/
|
|
384
|
+
function decodeAccountPermissionUpdateContract(base64) {
|
|
385
|
+
const accountUpdateContract = tron_1.protocol.AccountPermissionUpdateContract.decode(Buffer.from(base64, 'base64')).toJSON();
|
|
386
|
+
(0, assert_1.default)(accountUpdateContract.ownerAddress);
|
|
387
|
+
(0, assert_1.default)(accountUpdateContract.owner);
|
|
388
|
+
(0, assert_1.default)(accountUpdateContract.hasOwnProperty('actives'));
|
|
389
|
+
const ownerAddress = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(accountUpdateContract.ownerAddress, 'base64').toString('hex')));
|
|
390
|
+
const owner = createPermission(accountUpdateContract.owner);
|
|
391
|
+
let witness = undefined;
|
|
392
|
+
if (accountUpdateContract.witness) {
|
|
393
|
+
witness = createPermission(accountUpdateContract.witness);
|
|
394
|
+
}
|
|
395
|
+
const activeList = accountUpdateContract.actives.map((active) => createPermission(active));
|
|
396
|
+
return {
|
|
397
|
+
ownerAddress,
|
|
398
|
+
owner,
|
|
399
|
+
witness,
|
|
400
|
+
actives: activeList,
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Deserialize the segment of the txHex corresponding with freeze balance contract
|
|
405
|
+
*
|
|
406
|
+
* @param {string} base64 - The base64 encoded contract data
|
|
407
|
+
* @returns {FreezeBalanceContractParameter[]} - Array containing the decoded freeze contract
|
|
408
|
+
*/
|
|
409
|
+
function decodeFreezeBalanceV2Contract(base64) {
|
|
410
|
+
let freezeContract;
|
|
411
|
+
try {
|
|
412
|
+
freezeContract = tron_1.protocol.FreezeBalanceV2Contract.decode(Buffer.from(base64, 'base64')).toJSON();
|
|
413
|
+
}
|
|
414
|
+
catch (e) {
|
|
415
|
+
throw new sdk_core_1.UtilsError('There was an error decoding the freeze contract in the transaction.');
|
|
416
|
+
}
|
|
417
|
+
if (!freezeContract.ownerAddress) {
|
|
418
|
+
throw new sdk_core_1.UtilsError('Owner address does not exist in this freeze contract.');
|
|
419
|
+
}
|
|
420
|
+
if (freezeContract.resource === undefined) {
|
|
421
|
+
throw new sdk_core_1.UtilsError('Resource type does not exist in this freeze contract.');
|
|
422
|
+
}
|
|
423
|
+
if (freezeContract.frozenBalance === undefined) {
|
|
424
|
+
throw new sdk_core_1.UtilsError('Frozen balance does not exist in this freeze contract.');
|
|
425
|
+
}
|
|
426
|
+
const owner_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(freezeContract.ownerAddress, 'base64').toString('hex')));
|
|
427
|
+
const resourceValue = freezeContract.resource === 0 ? enum_1.TronResource.BANDWIDTH : enum_1.TronResource.ENERGY;
|
|
428
|
+
return [
|
|
429
|
+
{
|
|
430
|
+
parameter: {
|
|
431
|
+
value: {
|
|
432
|
+
resource: resourceValue,
|
|
433
|
+
frozen_balance: Number(freezeContract.frozenBalance),
|
|
434
|
+
owner_address,
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
];
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Deserialize the segment of the txHex corresponding with vote witness contract
|
|
442
|
+
*
|
|
443
|
+
* @param {string} base64 - The base64 encoded contract data
|
|
444
|
+
* @returns {VoteWitnessContractParameter[]} - Array containing the decoded vote witness contract
|
|
445
|
+
*/
|
|
446
|
+
function decodeVoteWitnessContract(base64) {
|
|
447
|
+
let voteContract;
|
|
448
|
+
try {
|
|
449
|
+
voteContract = tron_1.protocol.VoteWitnessContract.decode(Buffer.from(base64, 'base64')).toJSON();
|
|
450
|
+
}
|
|
451
|
+
catch (e) {
|
|
452
|
+
throw new sdk_core_1.UtilsError('There was an error decoding the vote contract in the transaction.');
|
|
453
|
+
}
|
|
454
|
+
if (!voteContract.ownerAddress) {
|
|
455
|
+
throw new sdk_core_1.UtilsError('Owner address does not exist in this vote contract.');
|
|
456
|
+
}
|
|
457
|
+
if (!Array.isArray(voteContract.votes) || voteContract.votes.length === 0) {
|
|
458
|
+
throw new sdk_core_1.UtilsError('Votes do not exist or are empty in this vote contract.');
|
|
459
|
+
}
|
|
460
|
+
// deserialize attributes
|
|
461
|
+
const owner_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(voteContract.ownerAddress, 'base64').toString('hex')));
|
|
462
|
+
const votes = voteContract.votes.map((vote) => {
|
|
463
|
+
if (!vote.voteAddress) {
|
|
464
|
+
throw new sdk_core_1.UtilsError('Vote address is missing in one of the votes.');
|
|
465
|
+
}
|
|
466
|
+
return {
|
|
467
|
+
vote_address: getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(vote.voteAddress, 'base64').toString('hex'))),
|
|
468
|
+
vote_count: Number(vote.voteCount || 0),
|
|
469
|
+
};
|
|
470
|
+
});
|
|
471
|
+
return [
|
|
472
|
+
{
|
|
473
|
+
parameter: {
|
|
474
|
+
value: {
|
|
475
|
+
owner_address,
|
|
476
|
+
votes,
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
];
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Deserialize the segment of the txHex corresponding with unfreeze balance contract
|
|
484
|
+
*
|
|
485
|
+
* @param {string} base64 - The base64 encoded contract data
|
|
486
|
+
* @returns {UnfreezeBalanceContractParameter[]} - Array containing the decoded unfreeze contract
|
|
487
|
+
*/
|
|
488
|
+
function decodeUnfreezeBalanceV2Contract(base64) {
|
|
489
|
+
let unfreezeContract;
|
|
490
|
+
try {
|
|
491
|
+
unfreezeContract = tron_1.protocol.UnfreezeBalanceV2Contract.decode(Buffer.from(base64, 'base64')).toJSON();
|
|
492
|
+
}
|
|
493
|
+
catch (e) {
|
|
494
|
+
throw new sdk_core_1.UtilsError('There was an error decoding the unfreeze contract in the transaction.');
|
|
495
|
+
}
|
|
496
|
+
if (!unfreezeContract.ownerAddress) {
|
|
497
|
+
throw new sdk_core_1.UtilsError('Owner address does not exist in this unfreeze contract.');
|
|
498
|
+
}
|
|
499
|
+
if (unfreezeContract.resource === undefined) {
|
|
500
|
+
throw new sdk_core_1.UtilsError('Resource type does not exist in this unfreeze contract.');
|
|
501
|
+
}
|
|
502
|
+
if (unfreezeContract.unfreezeBalance === undefined) {
|
|
503
|
+
throw new sdk_core_1.UtilsError('Unfreeze balance does not exist in this unfreeze contract.');
|
|
504
|
+
}
|
|
505
|
+
// deserialize attributes
|
|
506
|
+
const owner_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(unfreezeContract.ownerAddress, 'base64').toString('hex')));
|
|
507
|
+
// Convert ResourceCode enum value to string resource name
|
|
508
|
+
const resourceValue = unfreezeContract.resource;
|
|
509
|
+
const resourceEnum = resourceValue === tron_1.protocol.ResourceCode.BANDWIDTH ? enum_1.TronResource.BANDWIDTH : enum_1.TronResource.ENERGY;
|
|
510
|
+
return [
|
|
511
|
+
{
|
|
512
|
+
parameter: {
|
|
513
|
+
value: {
|
|
514
|
+
resource: resourceEnum,
|
|
515
|
+
unfreeze_balance: Number(unfreezeContract.unfreezeBalance),
|
|
516
|
+
owner_address,
|
|
517
|
+
},
|
|
518
|
+
},
|
|
519
|
+
},
|
|
520
|
+
];
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Deserialize the segment of the txHex corresponding with withdraw balance contract
|
|
524
|
+
* Decoded contract is the same as withdraw expire unfreeze
|
|
525
|
+
*
|
|
526
|
+
* @param {string} base64 - The base64 encoded contract data
|
|
527
|
+
* @returns {WithdrawExpireUnfreezeContractParameter[]} - Array containing the decoded withdraw contract
|
|
528
|
+
*/
|
|
529
|
+
function decodeWithdrawBalanceContract(base64) {
|
|
530
|
+
let withdrawContract;
|
|
531
|
+
try {
|
|
532
|
+
withdrawContract = tron_1.protocol.WithdrawBalanceContract.decode(Buffer.from(base64, 'base64')).toJSON();
|
|
533
|
+
}
|
|
534
|
+
catch (e) {
|
|
535
|
+
throw new sdk_core_1.UtilsError('There was an error decoding the withdraw contract in the transaction.');
|
|
536
|
+
}
|
|
537
|
+
if (!withdrawContract.ownerAddress) {
|
|
538
|
+
throw new sdk_core_1.UtilsError('Owner address does not exist in this withdraw contract.');
|
|
539
|
+
}
|
|
540
|
+
// deserialize attributes
|
|
541
|
+
const owner_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(withdrawContract.ownerAddress, 'base64').toString('hex')));
|
|
542
|
+
return [
|
|
543
|
+
{
|
|
544
|
+
parameter: {
|
|
545
|
+
value: {
|
|
546
|
+
owner_address,
|
|
547
|
+
},
|
|
548
|
+
},
|
|
549
|
+
},
|
|
550
|
+
];
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Deserialize the segment of the txHex corresponding with withdraw expire unfreeze contract
|
|
554
|
+
*
|
|
555
|
+
* @param {string} base64 - The base64 encoded contract data
|
|
556
|
+
* @returns {WithdrawExpireUnfreezeContractParameter[]} - Array containing the decoded withdraw contract
|
|
557
|
+
*/
|
|
558
|
+
function decodeWithdrawExpireUnfreezeContract(base64) {
|
|
559
|
+
let withdrawContract;
|
|
560
|
+
try {
|
|
561
|
+
withdrawContract = tron_1.protocol.WithdrawBalanceContract.decode(Buffer.from(base64, 'base64')).toJSON();
|
|
562
|
+
}
|
|
563
|
+
catch (e) {
|
|
564
|
+
throw new sdk_core_1.UtilsError('There was an error decoding the withdraw contract in the transaction.');
|
|
565
|
+
}
|
|
566
|
+
if (!withdrawContract.ownerAddress) {
|
|
567
|
+
throw new sdk_core_1.UtilsError('Owner address does not exist in this withdraw contract.');
|
|
568
|
+
}
|
|
569
|
+
// deserialize attributes
|
|
570
|
+
const owner_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(withdrawContract.ownerAddress, 'base64').toString('hex')));
|
|
571
|
+
return [
|
|
572
|
+
{
|
|
573
|
+
parameter: {
|
|
574
|
+
value: {
|
|
575
|
+
owner_address,
|
|
576
|
+
},
|
|
577
|
+
},
|
|
578
|
+
},
|
|
579
|
+
];
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Deserialize the segment of the txHex corresponding with delegate resource contract
|
|
583
|
+
*
|
|
584
|
+
* @param {string} base64 - The base64 encoded contract data
|
|
585
|
+
* @returns {ResourceManagementContractParameter[]} - Array containing the decoded delegate resource contract
|
|
586
|
+
*/
|
|
587
|
+
function decodeDelegateResourceContract(base64) {
|
|
588
|
+
let delegateResourceContract;
|
|
589
|
+
try {
|
|
590
|
+
delegateResourceContract = tron_1.protocol.DelegateResourceContract.decode(Buffer.from(base64, 'base64')).toJSON();
|
|
591
|
+
}
|
|
592
|
+
catch (e) {
|
|
593
|
+
throw new sdk_core_1.UtilsError('There was an error decoding the delegate resource contract in the transaction.');
|
|
594
|
+
}
|
|
595
|
+
if (!delegateResourceContract.ownerAddress) {
|
|
596
|
+
throw new sdk_core_1.UtilsError('Owner address does not exist in this delegate resource contract.');
|
|
597
|
+
}
|
|
598
|
+
if (!delegateResourceContract.receiverAddress) {
|
|
599
|
+
throw new sdk_core_1.UtilsError('Receiver address does not exist in this delegate resource contract.');
|
|
600
|
+
}
|
|
601
|
+
if (delegateResourceContract.resource === undefined) {
|
|
602
|
+
throw new sdk_core_1.UtilsError('Resource type does not exist in this delegate resource contract.');
|
|
603
|
+
}
|
|
604
|
+
if (delegateResourceContract.balance === undefined) {
|
|
605
|
+
throw new sdk_core_1.UtilsError('Balance does not exist in this delegate resource contract.');
|
|
606
|
+
}
|
|
607
|
+
const owner_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(delegateResourceContract.ownerAddress, 'base64').toString('hex')));
|
|
608
|
+
const receiver_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(delegateResourceContract.receiverAddress, 'base64').toString('hex')));
|
|
609
|
+
const resourceValue = !delegateResourceContract.resource ? enum_1.TronResource.BANDWIDTH : enum_1.TronResource.ENERGY;
|
|
610
|
+
return [
|
|
611
|
+
{
|
|
612
|
+
parameter: {
|
|
613
|
+
value: {
|
|
614
|
+
resource: resourceValue,
|
|
615
|
+
balance: Number(delegateResourceContract.balance),
|
|
616
|
+
owner_address,
|
|
617
|
+
receiver_address,
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
},
|
|
621
|
+
];
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Deserialize the segment of the txHex corresponding with undelegate resource contract
|
|
625
|
+
*
|
|
626
|
+
* @param {string} base64 - The base64 encoded contract data
|
|
627
|
+
* @returns {ResourceManagementContractParameter[]} - Array containing the decoded undelegate resource contract
|
|
628
|
+
*/
|
|
629
|
+
function decodeUnDelegateResourceContract(base64) {
|
|
630
|
+
let undelegateResourceContract;
|
|
631
|
+
try {
|
|
632
|
+
undelegateResourceContract = tron_1.protocol.UnDelegateResourceContract.decode(Buffer.from(base64, 'base64')).toJSON();
|
|
633
|
+
}
|
|
634
|
+
catch (e) {
|
|
635
|
+
throw new sdk_core_1.UtilsError('There was an error decoding the delegate resource contract in the transaction.');
|
|
636
|
+
}
|
|
637
|
+
if (!undelegateResourceContract.ownerAddress) {
|
|
638
|
+
throw new sdk_core_1.UtilsError('Owner address does not exist in this delegate resource contract.');
|
|
639
|
+
}
|
|
640
|
+
if (!undelegateResourceContract.receiverAddress) {
|
|
641
|
+
throw new sdk_core_1.UtilsError('Receiver address does not exist in this delegate resource contract.');
|
|
642
|
+
}
|
|
643
|
+
if (undelegateResourceContract.resource === undefined) {
|
|
644
|
+
throw new sdk_core_1.UtilsError('Resource type does not exist in this delegate resource contract.');
|
|
645
|
+
}
|
|
646
|
+
if (undelegateResourceContract.balance === undefined) {
|
|
647
|
+
throw new sdk_core_1.UtilsError('Balance does not exist in this delegate resource contract.');
|
|
648
|
+
}
|
|
649
|
+
const owner_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(undelegateResourceContract.ownerAddress, 'base64').toString('hex')));
|
|
650
|
+
const receiver_address = getBase58AddressFromByteArray(getByteArrayFromHexAddress(Buffer.from(undelegateResourceContract.receiverAddress, 'base64').toString('hex')));
|
|
651
|
+
const resourceValue = !undelegateResourceContract.resource ? enum_1.TronResource.BANDWIDTH : enum_1.TronResource.ENERGY;
|
|
652
|
+
return [
|
|
653
|
+
{
|
|
654
|
+
parameter: {
|
|
655
|
+
value: {
|
|
656
|
+
resource: resourceValue,
|
|
657
|
+
balance: Number(undelegateResourceContract.balance),
|
|
658
|
+
owner_address,
|
|
659
|
+
receiver_address,
|
|
660
|
+
},
|
|
661
|
+
},
|
|
662
|
+
},
|
|
663
|
+
];
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* @param raw
|
|
667
|
+
*/
|
|
668
|
+
function createPermission(raw) {
|
|
669
|
+
let permissionType;
|
|
670
|
+
const permission = raw.permissionName.toLowerCase().trim();
|
|
671
|
+
if (permission === 'owner') {
|
|
672
|
+
permissionType = enum_1.PermissionType.Owner;
|
|
673
|
+
}
|
|
674
|
+
else if (permission === 'witness') {
|
|
675
|
+
permissionType = enum_1.PermissionType.Witness;
|
|
676
|
+
}
|
|
677
|
+
else if (permission.substr(0, 6) === 'active') {
|
|
678
|
+
permissionType = enum_1.PermissionType.Active;
|
|
679
|
+
}
|
|
680
|
+
else {
|
|
681
|
+
throw new sdk_core_1.UtilsError('Permission type not parseable.');
|
|
682
|
+
}
|
|
683
|
+
return { type: permissionType, threshold: raw.threshold };
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* @param rawTransaction
|
|
687
|
+
*/
|
|
688
|
+
function isValidTxJsonString(rawTransaction) {
|
|
689
|
+
const transaction = JSON.parse(rawTransaction);
|
|
690
|
+
return transaction.hasOwnProperty('txID');
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Returns whether the provided raw transaction accommodates to bitgo's preferred format
|
|
694
|
+
*
|
|
695
|
+
* @param {any} rawTransaction - The raw transaction to be checked
|
|
696
|
+
* @returns {boolean} the validation result
|
|
697
|
+
*/
|
|
698
|
+
function isValidRawTransactionFormat(rawTransaction) {
|
|
699
|
+
if (typeof rawTransaction === 'string' && (isValidHex(rawTransaction) || isValidTxJsonString(rawTransaction))) {
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
return false;
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Returns an hex string of the given buffer
|
|
706
|
+
*
|
|
707
|
+
* @param {Buffer | Uint8Array} buffer - the buffer to be converted to hex
|
|
708
|
+
* @returns {string} - the hex value
|
|
709
|
+
*/
|
|
710
|
+
function toHex(buffer) {
|
|
711
|
+
return hex.encode(buffer, true);
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Returns a Keccak-256 encoded string of the parameters
|
|
715
|
+
*
|
|
716
|
+
* @param types - strings describing the types of the values
|
|
717
|
+
* @param values - value to encode
|
|
718
|
+
* @param methodId - the first 4 bytes of the function selector
|
|
719
|
+
*/
|
|
720
|
+
function encodeDataParams(types, values, methodId) {
|
|
721
|
+
types.forEach((type, index) => {
|
|
722
|
+
if (type == 'address') {
|
|
723
|
+
values[index] = values[index].replace(ADDRESS_PREFIX_REGEX, '0x');
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
const abiCoder = new utils_1.AbiCoder();
|
|
727
|
+
let data;
|
|
728
|
+
try {
|
|
729
|
+
data = abiCoder.encode(types, values);
|
|
730
|
+
}
|
|
731
|
+
catch (e) {
|
|
732
|
+
throw new sdk_core_1.UtilsError(`There was an error encoding the data params. Error = ${JSON.stringify(e)}`);
|
|
733
|
+
}
|
|
734
|
+
if (methodId) {
|
|
735
|
+
return (0, utils_1.hexConcat)([methodId, data]).replace(/^(0x)/, '');
|
|
736
|
+
}
|
|
737
|
+
else {
|
|
738
|
+
return data.replace(/^(0x)/, '');
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Returns the decoded values according to the array of types
|
|
743
|
+
*
|
|
744
|
+
* @param types - strings describing the types of the values
|
|
745
|
+
* @param data - encoded string
|
|
746
|
+
*/
|
|
747
|
+
function decodeDataParams(types, data) {
|
|
748
|
+
const abiCoder = new utils_1.AbiCoder();
|
|
749
|
+
data = '0x' + data.substring(8);
|
|
750
|
+
return abiCoder.decode(types, data).reduce((obj, arg, index) => {
|
|
751
|
+
if (types[index] == 'address')
|
|
752
|
+
arg = ADDRESS_PREFIX + arg.substr(2).toLowerCase();
|
|
753
|
+
obj.push(arg);
|
|
754
|
+
return obj;
|
|
755
|
+
}, []);
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Generate raw_data_hex for a TRON transaction
|
|
759
|
+
*
|
|
760
|
+
* @param {Object} rawData - The transaction raw data object containing:
|
|
761
|
+
* @param {Array} rawData.contract - Array of contract objects
|
|
762
|
+
* @param {string} rawData.refBlockBytes - Reference block bytes
|
|
763
|
+
* @param {string} rawData.refBlockHash - Reference block hash
|
|
764
|
+
* @param {number} rawData.expiration - Transaction expiration timestamp
|
|
765
|
+
* @param {number} rawData.timestamp - Transaction creation timestamp
|
|
766
|
+
* @param {number} [rawData.feeLimit] - Optional fee limit for smart contracts
|
|
767
|
+
* @returns {string} The hex string representation of the encoded transaction data
|
|
768
|
+
*/
|
|
769
|
+
function generateRawDataHex(rawData = {}) {
|
|
770
|
+
try {
|
|
771
|
+
// Process contracts to ensure proper protobuf encoding
|
|
772
|
+
let processedContracts = rawData.contract;
|
|
773
|
+
if (rawData.contract && rawData.contract.length > 0) {
|
|
774
|
+
processedContracts = rawData.contract.map((contract) => {
|
|
775
|
+
// Handle TransferContract specifically
|
|
776
|
+
if (contract.parameter?.type_url === 'type.googleapis.com/protocol.TransferContract') {
|
|
777
|
+
const contractValue = contract.parameter.value;
|
|
778
|
+
// Create the protobuf contract object
|
|
779
|
+
const transferContract = {};
|
|
780
|
+
// Handle owner_address (required field)
|
|
781
|
+
if (contractValue.owner_address) {
|
|
782
|
+
transferContract.ownerAddress = Buffer.from(contractValue.owner_address, 'hex');
|
|
783
|
+
}
|
|
784
|
+
// Handle to_address (required field)
|
|
785
|
+
if (contractValue.to_address) {
|
|
786
|
+
transferContract.toAddress = Buffer.from(contractValue.to_address, 'hex');
|
|
787
|
+
}
|
|
788
|
+
// Handle amount (required field)
|
|
789
|
+
if (contractValue.amount !== undefined) {
|
|
790
|
+
transferContract.amount = contractValue.amount;
|
|
791
|
+
}
|
|
792
|
+
// Encode the contract using protobuf
|
|
793
|
+
const encodedContract = tron_1.protocol.TransferContract.encode(transferContract).finish();
|
|
794
|
+
const base64Value = Buffer.from(encodedContract).toString('base64');
|
|
795
|
+
return {
|
|
796
|
+
...contract,
|
|
797
|
+
parameter: {
|
|
798
|
+
...contract.parameter,
|
|
799
|
+
value: base64Value,
|
|
800
|
+
},
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
return contract;
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
// Create raw transaction object matching protobuf schema
|
|
807
|
+
const rawTx = {
|
|
808
|
+
contract: processedContracts,
|
|
809
|
+
refBlockBytes: rawData.refBlockBytes ? Buffer.from(rawData.refBlockBytes, 'hex') : undefined,
|
|
810
|
+
refBlockHash: rawData.refBlockHash ? Buffer.from(rawData.refBlockHash, 'hex') : undefined,
|
|
811
|
+
expiration: rawData.expiration,
|
|
812
|
+
timestamp: rawData.timestamp,
|
|
813
|
+
feeLimit: rawData.feeLimit,
|
|
814
|
+
};
|
|
815
|
+
// Encode using protobuf and get final bytes
|
|
816
|
+
const encodedBytes = tron_1.protocol.Transaction.raw.encode(rawTx).finish();
|
|
817
|
+
// Convert to hex string
|
|
818
|
+
return Buffer.from(encodedBytes).toString('hex');
|
|
819
|
+
}
|
|
820
|
+
catch (e) {
|
|
821
|
+
throw new sdk_core_1.UtilsError('Failed to generate raw data hex: ' + e.message);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXlEQSwwQ0FFQztBQUtELGdFQUVDO0FBS0QsZ0VBRUM7QUFRRCwwQ0FtQkM7QUFLRCx3RUFTQztBQUlELGtEQUVDO0FBS0Qsb0RBRUM7QUFLRCxzRUFFQztBQUtELDBEQUdDO0FBTUQsMENBRUM7QUFPRCxnQ0FFQztBQUtELDBEQUVDO0FBT0QsOENBMkVDO0FBU0Qsb0RBMEJDO0FBUUQsNENBR0M7QUFPRCxnQ0FFQztBQU1ELHdEQTBDQztBQVFELGdFQXVDQztBQVNELHNGQXNCQztBQVFELHNFQXFDQztBQVFELDhEQWlEQztBQVFELDBFQXdDQztBQVNELHNFQTBCQztBQVFELG9GQTBCQztBQVFELHdFQThDQztBQVFELDRFQThDQztBQXVCRCxrREFHQztBQVFELGtFQUtDO0FBUUQsc0JBRUM7QUFTRCw0Q0FtQkM7QUFRRCw0Q0FRQztBQWNELGdEQXdFQztBQXY2QkQsb0RBQTRCO0FBQzVCLG9EQUFzQztBQUN0QyxpREFBbUM7QUFDbkMsd0RBQXlEO0FBRXpELG1EQUFrRDtBQUNsRCxpREFBMkQ7QUFtQjNELGlDQUFvRTtBQUNwRSw0Q0FBdUQ7QUFDdkQsMkNBQWtEO0FBRXJDLFFBQUEsMEJBQTBCLEdBQUcsUUFBUSxDQUFDLENBQUMsVUFBVTtBQUNqRCxRQUFBLDhCQUE4QixHQUFHLE9BQU8sQ0FBQyxDQUFDLFdBQVc7QUFDbEUsTUFBTSxvQkFBb0IsR0FBRyxPQUFPLENBQUM7QUFDckMsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDO0FBSTVCLE1BQU0sYUFBYSxHQUFHLENBQUMsT0FBTyxHQUFHLFNBQVMsRUFBRSxFQUFFO0lBQzVDLE9BQ0UsZUFBSztTQUNGLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxLQUFLLENBQUM7U0FDdkMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxPQUFPLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FDL0QsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztBQUNyRCxDQUFDLENBQUM7QUFFVyxRQUFBLDZCQUE2QixHQUFHLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUN6RCxRQUFBLDZCQUE2QixHQUFHLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQU96RCxRQUFBLG9CQUFvQixHQUFHLENBQUMsUUFBUSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0FBRTVEOztHQUVHO0FBQ0gsU0FBZ0IsZUFBZSxDQUFDLE9BQWU7SUFDN0MsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDdEQsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsMEJBQTBCLENBQUMsR0FBVztJQUNwRCxPQUFPLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDcEUsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsMEJBQTBCLENBQUMsR0FBYztJQUN2RCxPQUFPLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ2xELENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLGVBQWUsQ0FDN0IsZUFBdUIsRUFDdkIsYUFBcUIsRUFDckIsTUFBYyxFQUNkLGFBQWEsR0FBRyxJQUFJO0lBRXBCLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUN4QixNQUFNLElBQUkscUJBQVUsQ0FBQyw2REFBNkQsQ0FBQyxDQUFDO0lBQ3RGLENBQUM7SUFFRCxJQUFJLENBQUMsVUFBVSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7UUFDakMsTUFBTSxJQUFJLHFCQUFVLENBQUMsMkRBQTJELENBQUMsQ0FBQztJQUNwRixDQUFDO0lBRUQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1FBQ3BDLE1BQU0sSUFBSSxxQkFBVSxDQUFDLG9DQUFvQyxDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUVELE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsZUFBZSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsYUFBYSxDQUFDLENBQUM7QUFDNUYsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsOEJBQThCLENBQUMsTUFBYztJQUMzRCxzSEFBc0g7SUFDdEgsK0NBQStDO0lBQy9DLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9ELHlDQUF5QztJQUN6QyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN6QixPQUFPLDBCQUEwQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFDRCxNQUFNLElBQUkscUJBQVUsQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDO0FBQ3hFLENBQUM7QUFDRDs7R0FFRztBQUNILFNBQWdCLG1CQUFtQixDQUFDLFVBQTBCO0lBQzVELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsVUFBdUIsQ0FBQyxDQUFDO0FBQzNFLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLG9CQUFvQixDQUFDLFVBQTBCO0lBQzdELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsb0JBQW9CLENBQUMsVUFBdUIsQ0FBQyxDQUFDO0FBQzVFLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLDZCQUE2QixDQUFDLE9BQWtCO0lBQzlELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMscUJBQXFCLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDN0QsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsdUJBQXVCLENBQUMsR0FBVztJQUNqRCxNQUFNLEdBQUcsR0FBRywwQkFBMEIsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM1QyxPQUFPLDZCQUE2QixDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQzVDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFnQixlQUFlLENBQUMsVUFBOEIsRUFBRSxXQUErQjtJQUM3RixPQUFPLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxVQUFVLEVBQUUsV0FBVyxDQUF1QixDQUFDO0FBQzdGLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsVUFBVSxDQUFDLE9BQWUsRUFBRSxVQUE4QixFQUFFLGFBQWEsR0FBRyxJQUFJO0lBQzlGLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLFVBQW9CLEVBQUUsYUFBYSxDQUFDLENBQUM7QUFDOUUsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsdUJBQXVCLENBQUMsUUFBd0I7SUFDOUQsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsUUFBcUIsQ0FBQyxDQUFDO0FBQ3BFLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsaUJBQWlCLENBQUMsU0FBaUI7SUFDakQsTUFBTSxjQUFjLEdBQUcsb0JBQW9CLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFdkQsc0RBQXNEO0lBQ3RELElBQUksY0FBYyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDMUMsTUFBTSxJQUFJLHFCQUFVLENBQUMsd0NBQXdDLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBRUQsSUFBSSxRQVFxQyxDQUFDO0lBRTFDLElBQUksWUFBMEIsQ0FBQztJQUUvQix3Q0FBd0M7SUFDeEMsUUFBUSxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUN2RCxLQUFLLCtDQUErQztZQUNsRCxZQUFZLEdBQUcsbUJBQVksQ0FBQyxRQUFRLENBQUM7WUFDckMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN2RixNQUFNO1FBQ1IsS0FBSyw4REFBOEQ7WUFDakUsWUFBWSxHQUFHLG1CQUFZLENBQUMsdUJBQXVCLENBQUM7WUFDcEQsUUFBUSxHQUFHLE9BQU8sQ0FBQyxxQ0FBcUMsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN0RyxNQUFNO1FBQ1IsS0FBSyxtREFBbUQ7WUFDdEQsWUFBWSxHQUFHLG1CQUFZLENBQUMsb0JBQW9CLENBQUM7WUFDakQsUUFBUSxHQUFHLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMzRixNQUFNO1FBQ1IsS0FBSyxzREFBc0Q7WUFDekQsWUFBWSxHQUFHLG1CQUFZLENBQUMsZUFBZSxDQUFDO1lBQzVDLFFBQVEsR0FBRyw2QkFBNkIsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN0RixNQUFNO1FBQ1IsS0FBSyxrREFBa0Q7WUFDckQsWUFBWSxHQUFHLG1CQUFZLENBQUMsV0FBVyxDQUFDO1lBQ3hDLFFBQVEsR0FBRyx5QkFBeUIsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNsRixNQUFNO1FBQ1IsS0FBSyw2REFBNkQ7WUFDaEUsUUFBUSxHQUFHLG9DQUFvQyxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzdGLFlBQVksR0FBRyxtQkFBWSxDQUFDLHNCQUFzQixDQUFDO1lBQ25ELE1BQU07UUFDUixLQUFLLHNEQUFzRDtZQUN6RCxRQUFRLEdBQUcsNkJBQTZCLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdEYsWUFBWSxHQUFHLG1CQUFZLENBQUMsZUFBZSxDQUFDO1lBQzVDLE1BQU07UUFDUixLQUFLLHdEQUF3RDtZQUMzRCxRQUFRLEdBQUcsK0JBQStCLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDeEYsWUFBWSxHQUFHLG1CQUFZLENBQUMsaUJBQWlCLENBQUM7WUFDOUMsTUFBTTtRQUNSLEtBQUssK0JBQW1CO1lBQ3RCLFlBQVksR0FBRyxtQkFBWSxDQUFDLHdCQUF3QixDQUFDO1lBQ3JELFFBQVEsR0FBRyw4QkFBOEIsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN2RixNQUFNO1FBQ1IsS0FBSyx5REFBeUQ7WUFDNUQsWUFBWSxHQUFHLG1CQUFZLENBQUMsMEJBQTBCLENBQUM7WUFDdkQsUUFBUSxHQUFHLGdDQUFnQyxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3pGLE1BQU07UUFDUjtZQUNFLE1BQU0sSUFBSSxxQkFBVSxDQUFDLDJCQUEyQixDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUVELE9BQU87UUFDTCxZQUFZO1FBQ1osUUFBUTtRQUNSLFVBQVUsRUFBRSxjQUFjLENBQUMsVUFBVTtRQUNyQyxTQUFTLEVBQUUsY0FBYyxDQUFDLFNBQVM7UUFDbkMsZUFBZSxFQUFFLGNBQWMsQ0FBQyxVQUFVO1FBQzFDLGNBQWMsRUFBRSxjQUFjLENBQUMsU0FBUztRQUN4QyxTQUFTLEVBQUUsQ0FBQyxjQUFjLENBQUMsUUFBUTtLQUNwQyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLG9CQUFvQixDQUFDLFNBQWlCO0lBUXBELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRTVDLElBQUksR0FBRyxDQUFDO0lBQ1IsSUFBSSxDQUFDO1FBQ0gsaURBQWlEO1FBQ2pELEdBQUcsR0FBRyxlQUFRLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDWCxNQUFNLElBQUkscUJBQVUsQ0FBQyw4RUFBOEUsQ0FBQyxDQUFDO0lBQ3ZHLENBQUM7SUFFRCxPQUFPO1FBQ0wsVUFBVSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDO1FBQ2xDLFNBQVMsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQztRQUNoQyxTQUFTLEVBQUUsR0FBRyxDQUFDLFFBQVE7UUFDdkIsVUFBVSxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDO1FBQ3BDLFFBQVEsRUFBRSxHQUFHLENBQUMsUUFBUTtRQUN0QixTQUFTLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUM7S0FDbkMsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLGdCQUFnQixDQUFDLE1BQWM7SUFDN0MsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDN0MsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2hDLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsVUFBVSxDQUFDLEdBQVc7SUFDcEMsT0FBTyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDNUMsQ0FBQztBQUVEOzs7S0FHSztBQUNMLFNBQWdCLHNCQUFzQixDQUFDLFdBQW1CO0lBQ3hELE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3pELElBQUksZ0JBQWdCLENBQUM7SUFFckIsSUFBSSxDQUFDO1FBQ0gsZ0JBQWdCLEdBQUcsZUFBUSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNYLE1BQU0sSUFBSSxxQkFBVSxDQUFDLHVFQUF1RSxDQUFDLENBQUM7SUFDaEcsQ0FBQztJQUVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNuQyxNQUFNLElBQUkscUJBQVUsQ0FBQyx5REFBeUQsQ0FBQyxDQUFDO0lBQ2xGLENBQUM7SUFFRCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDaEMsTUFBTSxJQUFJLHFCQUFVLENBQUMsK0RBQStELENBQUMsQ0FBQztJQUN4RixDQUFDO0lBRUQsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQy9DLE1BQU0sSUFBSSxxQkFBVSxDQUFDLGtEQUFrRCxDQUFDLENBQUM7SUFDM0UsQ0FBQztJQUVELHlCQUF5QjtJQUN6QixNQUFNLGFBQWEsR0FBRyw2QkFBNkIsQ0FDakQsMEJBQTBCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQ2pHLENBQUM7SUFDRixNQUFNLFVBQVUsR0FBRyw2QkFBNkIsQ0FDOUMsMEJBQTBCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQzlGLENBQUM7SUFDRixNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUM7SUFFdkMsT0FBTztRQUNMO1lBQ0UsU0FBUyxFQUFFO2dCQUNULEtBQUssRUFBRTtvQkFDTCxNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQztvQkFDdEIsYUFBYTtvQkFDYixVQUFVO2lCQUNYO2FBQ0Y7U0FDRjtLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQiwwQkFBMEIsQ0FBQyxNQUFjO0lBQ3ZELElBQUksbUJBQW1CLENBQUM7SUFDeEIsSUFBSSxDQUFDO1FBQ0gsbUJBQW1CLEdBQUcsZUFBUSxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ3JHLENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1gsTUFBTSxJQUFJLHFCQUFVLENBQUMsbUVBQW1FLENBQUMsQ0FBQztJQUM1RixDQUFDO0lBRUQsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3RDLE1BQU0sSUFBSSxxQkFBVSxDQUFDLHFEQUFxRCxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUVELElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUN6QyxNQUFNLElBQUkscUJBQVUsQ0FBQyxvRUFBb0UsQ0FBQyxDQUFDO0lBQzdGLENBQUM7SUFFRCxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDOUIsTUFBTSxJQUFJLHFCQUFVLENBQUMsNENBQTRDLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBRUQseUJBQXlCO0lBQ3pCLE1BQU0sYUFBYSxHQUFHLDZCQUE2QixDQUNqRCwwQkFBMEIsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDcEcsQ0FBQztJQUNGLE1BQU0sZ0JBQWdCLEdBQUcsNkJBQTZCLENBQ3BELDBCQUEwQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsZUFBZSxFQUFFLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUN2RyxDQUFDO0lBQ0YsTUFBTSxJQUFJLEdBQUcsbUJBQW1CLENBQUMsSUFBSSxDQUFDO0lBQ3RDLE9BQU87UUFDTDtZQUNFLFNBQVMsRUFBRTtnQkFDVCxLQUFLLEVBQUU7b0JBQ0wsSUFBSSxFQUFFLElBQUk7b0JBQ1YsYUFBYTtvQkFDYixnQkFBZ0I7aUJBQ2pCO2FBQ0Y7U0FDRjtLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBZ0IscUNBQXFDLENBQUMsTUFBYztJQUNsRSxNQUFNLHFCQUFxQixHQUFHLGVBQVEsQ0FBQywrQkFBK0IsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUN0SCxJQUFBLGdCQUFNLEVBQUMscUJBQXFCLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDM0MsSUFBQSxnQkFBTSxFQUFDLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3BDLElBQUEsZ0JBQU0sRUFBQyxxQkFBcUIsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUV4RCxNQUFNLFlBQVksR0FBRyw2QkFBNkIsQ0FDaEQsMEJBQTBCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQ3RHLENBQUM7SUFDRixNQUFNLEtBQUssR0FBZSxnQkFBZ0IsQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN4RSxJQUFJLE9BQU8sR0FBMkIsU0FBUyxDQUFDO0lBQ2hELElBQUkscUJBQXFCLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDbEMsT0FBTyxHQUFHLGdCQUFnQixDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFDRCxNQUFNLFVBQVUsR0FBRyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBRTNGLE9BQU87UUFDTCxZQUFZO1FBQ1osS0FBSztRQUNMLE9BQU87UUFDUCxPQUFPLEVBQUUsVUFBVTtLQUNwQixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsNkJBQTZCLENBQUMsTUFBYztJQUMxRCxJQUFJLGNBQXFDLENBQUM7SUFDMUMsSUFBSSxDQUFDO1FBQ0gsY0FBYyxHQUFHLGVBQVEsQ0FBQyx1QkFBdUIsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNuRyxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNYLE1BQU0sSUFBSSxxQkFBVSxDQUFDLHFFQUFxRSxDQUFDLENBQUM7SUFDOUYsQ0FBQztJQUVELElBQUksQ0FBQyxjQUFjLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDakMsTUFBTSxJQUFJLHFCQUFVLENBQUMsdURBQXVELENBQUMsQ0FBQztJQUNoRixDQUFDO0lBRUQsSUFBSSxjQUFjLENBQUMsUUFBUSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzFDLE1BQU0sSUFBSSxxQkFBVSxDQUFDLHVEQUF1RCxDQUFDLENBQUM7SUFDaEYsQ0FBQztJQUVELElBQUksY0FBYyxDQUFDLGFBQWEsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUMvQyxNQUFNLElBQUkscUJBQVUsQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO0lBQ2pGLENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBRyw2QkFBNkIsQ0FDakQsMEJBQTBCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUMvRixDQUFDO0lBRUYsTUFBTSxhQUFhLEdBQUcsY0FBYyxDQUFDLFFBQVEsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLG1CQUFZLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxtQkFBWSxDQUFDLE1BQU0sQ0FBQztJQUVuRyxPQUFPO1FBQ0w7WUFDRSxTQUFTLEVBQUU7Z0JBQ1QsS0FBSyxFQUFFO29CQUNMLFFBQVEsRUFBRSxhQUFhO29CQUN2QixjQUFjLEVBQUUsTUFBTSxDQUFDLGNBQWMsQ0FBQyxhQUFhLENBQUM7b0JBQ3BELGFBQWE7aUJBQ2Q7YUFDRjtTQUNGO0tBQ0YsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLHlCQUF5QixDQUFDLE1BQWM7SUFDdEQsSUFBSSxZQUFpQyxDQUFDO0lBQ3RDLElBQUksQ0FBQztRQUNILFlBQVksR0FBRyxlQUFRLENBQUMsbUJBQW1CLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDN0YsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDWCxNQUFNLElBQUkscUJBQVUsQ0FBQyxtRUFBbUUsQ0FBQyxDQUFDO0lBQzVGLENBQUM7SUFFRCxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQy9CLE1BQU0sSUFBSSxxQkFBVSxDQUFDLHFEQUFxRCxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUVELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsSUFBSSxZQUFZLENBQUMsS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUMxRSxNQUFNLElBQUkscUJBQVUsQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO0lBQ2pGLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsTUFBTSxhQUFhLEdBQUcsNkJBQTZCLENBQ2pELDBCQUEwQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDN0YsQ0FBQztJQU9GLE1BQU0sS0FBSyxHQUFHLFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBYyxFQUFFLEVBQUU7UUFDdEQsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN0QixNQUFNLElBQUkscUJBQVUsQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1FBQ3ZFLENBQUM7UUFFRCxPQUFPO1lBQ0wsWUFBWSxFQUFFLDZCQUE2QixDQUN6QywwQkFBMEIsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQ3BGO1lBQ0QsVUFBVSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxJQUFJLENBQUMsQ0FBQztTQUN4QyxDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPO1FBQ0w7WUFDRSxTQUFTLEVBQUU7Z0JBQ1QsS0FBSyxFQUFFO29CQUNMLGFBQWE7b0JBQ2IsS0FBSztpQkFDTjthQUNGO1NBQ0Y7S0FDRixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsK0JBQStCLENBQUMsTUFBYztJQUM1RCxJQUFJLGdCQUF5QyxDQUFDO0lBQzlDLElBQUksQ0FBQztRQUNILGdCQUFnQixHQUFHLGVBQVEsQ0FBQyx5QkFBeUIsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUN2RyxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNYLE1BQU0sSUFBSSxxQkFBVSxDQUFDLHVFQUF1RSxDQUFDLENBQUM7SUFDaEcsQ0FBQztJQUVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNuQyxNQUFNLElBQUkscUJBQVUsQ0FBQyx5REFBeUQsQ0FBQyxDQUFDO0lBQ2xGLENBQUM7SUFFRCxJQUFJLGdCQUFnQixDQUFDLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUM1QyxNQUFNLElBQUkscUJBQVUsQ0FBQyx5REFBeUQsQ0FBQyxDQUFDO0lBQ2xGLENBQUM7SUFFRCxJQUFJLGdCQUFnQixDQUFDLGVBQWUsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNuRCxNQUFNLElBQUkscUJBQVUsQ0FBQyw0REFBNEQsQ0FBQyxDQUFDO0lBQ3JGLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsTUFBTSxhQUFhLEdBQUcsNkJBQTZCLENBQ2pELDBCQUEwQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUNqRyxDQUFDO0lBRUYsMERBQTBEO0lBQzFELE1BQU0sYUFBYSxHQUFHLGdCQUFnQixDQUFDLFFBQVEsQ0FBQztJQUNoRCxNQUFNLFlBQVksR0FBRyxhQUFhLEtBQUssZUFBUSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLG1CQUFZLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxtQkFBWSxDQUFDLE1BQU0sQ0FBQztJQUV0SCxPQUFPO1FBQ0w7WUFDRSxTQUFTLEVBQUU7Z0JBQ1QsS0FBSyxFQUFFO29CQUNMLFFBQVEsRUFBRSxZQUFZO29CQUN0QixnQkFBZ0IsRUFBRSxNQUFNLENBQUMsZ0JBQWdCLENBQUMsZUFBZSxDQUFDO29CQUMxRCxhQUFhO2lCQUNkO2FBQ0Y7U0FDRjtLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBZ0IsNkJBQTZCLENBQUMsTUFBYztJQUMxRCxJQUFJLGdCQUF5QyxDQUFDO0lBQzlDLElBQUksQ0FBQztRQUNILGdCQUFnQixHQUFHLGVBQVEsQ0FBQyx1QkFBdUIsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNyRyxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNYLE1BQU0sSUFBSSxxQkFBVSxDQUFDLHVFQUF1RSxDQUFDLENBQUM7SUFDaEcsQ0FBQztJQUVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNuQyxNQUFNLElBQUkscUJBQVUsQ0FBQyx5REFBeUQsQ0FBQyxDQUFDO0lBQ2xGLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsTUFBTSxhQUFhLEdBQUcsNkJBQTZCLENBQ2pELDBCQUEwQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUNqRyxDQUFDO0lBRUYsT0FBTztRQUNMO1lBQ0UsU0FBUyxFQUFFO2dCQUNULEtBQUssRUFBRTtvQkFDTCxhQUFhO2lCQUNkO2FBQ0Y7U0FDRjtLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixvQ0FBb0MsQ0FBQyxNQUFjO0lBQ2pFLElBQUksZ0JBQXlDLENBQUM7SUFDOUMsSUFBSSxDQUFDO1FBQ0gsZ0JBQWdCLEdBQUcsZUFBUSxDQUFDLHVCQUF1QixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ3JHLENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1gsTUFBTSxJQUFJLHFCQUFVLENBQUMsdUVBQXVFLENBQUMsQ0FBQztJQUNoRyxDQUFDO0lBRUQsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ25DLE1BQU0sSUFBSSxxQkFBVSxDQUFDLHlEQUF5RCxDQUFDLENBQUM7SUFDbEYsQ0FBQztJQUVELHlCQUF5QjtJQUN6QixNQUFNLGFBQWEsR0FBRyw2QkFBNkIsQ0FDakQsMEJBQTBCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQ2pHLENBQUM7SUFFRixPQUFPO1FBQ0w7WUFDRSxTQUFTLEVBQUU7Z0JBQ1QsS0FBSyxFQUFFO29CQUNMLGFBQWE7aUJBQ2Q7YUFDRjtTQUNGO0tBQ0YsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLDhCQUE4QixDQUFDLE1BQWM7SUFDM0QsSUFBSSx3QkFBMkQsQ0FBQztJQUNoRSxJQUFJLENBQUM7UUFDSCx3QkFBd0IsR0FBRyxlQUFRLENBQUMsd0JBQXdCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDOUcsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDWCxNQUFNLElBQUkscUJBQVUsQ0FBQyxnRkFBZ0YsQ0FBQyxDQUFDO0lBQ3pHLENBQUM7SUFFRCxJQUFJLENBQUMsd0JBQXdCLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDM0MsTUFBTSxJQUFJLHFCQUFVLENBQUMsa0VBQWtFLENBQUMsQ0FBQztJQUMzRixDQUFDO0lBRUQsSUFBSSxDQUFDLHdCQUF3QixDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQzlDLE1BQU0sSUFBSSxxQkFBVSxDQUFDLHFFQUFxRSxDQUFDLENBQUM7SUFDOUYsQ0FBQztJQUVELElBQUksd0JBQXdCLENBQUMsUUFBUSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3BELE1BQU0sSUFBSSxxQkFBVSxDQUFDLGtFQUFrRSxDQUFDLENBQUM7SUFDM0YsQ0FBQztJQUVELElBQUksd0JBQXdCLENBQUMsT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ25ELE1BQU0sSUFBSSxxQkFBVSxDQUFDLDREQUE0RCxDQUFDLENBQUM7SUFDckYsQ0FBQztJQUVELE1BQU0sYUFBYSxHQUFHLDZCQUE2QixDQUNqRCwwQkFBMEIsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDekcsQ0FBQztJQUVGLE1BQU0sZ0JBQWdCLEdBQUcsNkJBQTZCLENBQ3BELDBCQUEwQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsZUFBZSxFQUFFLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUM1RyxDQUFDO0lBRUYsTUFBTSxhQUFhLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLG1CQUFZLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxtQkFBWSxDQUFDLE1BQU0sQ0FBQztJQUV4RyxPQUFPO1FBQ0w7WUFDRSxTQUFTLEVBQUU7Z0JBQ1QsS0FBSyxFQUFFO29CQUNMLFFBQVEsRUFBRSxhQUFhO29CQUN2QixPQUFPLEVBQUUsTUFBTSxDQUFDLHdCQUF3QixDQUFDLE9BQU8sQ0FBQztvQkFDakQsYUFBYTtvQkFDYixnQkFBZ0I7aUJBQ2pCO2FBQ0Y7U0FDRjtLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixnQ0FBZ0MsQ0FBQyxNQUFjO0lBQzdELElBQUksMEJBQTZELENBQUM7SUFDbEUsSUFBSSxDQUFDO1FBQ0gsMEJBQTBCLEdBQUcsZUFBUSxDQUFDLDBCQUEwQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ2xILENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1gsTUFBTSxJQUFJLHFCQUFVLENBQUMsZ0ZBQWdGLENBQUMsQ0FBQztJQUN6RyxDQUFDO0lBRUQsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFlBQVksRUFBRSxDQUFDO1FBQzdDLE1BQU0sSUFBSSxxQkFBVSxDQUFDLGtFQUFrRSxDQUFDLENBQUM7SUFDM0YsQ0FBQztJQUVELElBQUksQ0FBQywwQkFBMEIsQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUNoRCxNQUFNLElBQUkscUJBQVUsQ0FBQyxxRUFBcUUsQ0FBQyxDQUFDO0lBQzlGLENBQUM7SUFFRCxJQUFJLDBCQUEwQixDQUFDLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUN0RCxNQUFNLElBQUkscUJBQVUsQ0FBQyxrRUFBa0UsQ0FBQyxDQUFDO0lBQzNGLENBQUM7SUFFRCxJQUFJLDBCQUEwQixDQUFDLE9BQU8sS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNyRCxNQUFNLElBQUkscUJBQVUsQ0FBQyw0REFBNEQsQ0FBQyxDQUFDO0lBQ3JGLENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBRyw2QkFBNkIsQ0FDakQsMEJBQTBCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQzNHLENBQUM7SUFFRixNQUFNLGdCQUFnQixHQUFHLDZCQUE2QixDQUNwRCwwQkFBMEIsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLGVBQWUsRUFBRSxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDOUcsQ0FBQztJQUVGLE1BQU0sYUFBYSxHQUFHLENBQUMsMEJBQTBCLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxtQkFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsbUJBQVksQ0FBQyxNQUFNLENBQUM7SUFFMUcsT0FBTztRQUNMO1lBQ0UsU0FBUyxFQUFFO2dCQUNULEtBQUssRUFBRTtvQkFDTCxRQUFRLEVBQUUsYUFBYTtvQkFDdkIsT0FBTyxFQUFFLE1BQU0sQ0FBQywwQkFBMEIsQ0FBQyxPQUFPLENBQUM7b0JBQ25ELGFBQWE7b0JBQ2IsZ0JBQWdCO2lCQUNqQjthQUNGO1NBQ0Y7S0FDRixDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxnQkFBZ0IsQ0FBQyxHQUFrRDtJQUMxRSxJQUFJLGNBQThCLENBQUM7SUFDbkMsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLGNBQWMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUMzRCxJQUFJLFVBQVUsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUMzQixjQUFjLEdBQUcscUJBQWMsQ0FBQyxLQUFLLENBQUM7SUFDeEMsQ0FBQztTQUFNLElBQUksVUFBVSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3BDLGNBQWMsR0FBRyxxQkFBYyxDQUFDLE9BQU8sQ0FBQztJQUMxQyxDQUFDO1NBQU0sSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUNoRCxjQUFjLEdBQUcscUJBQWMsQ0FBQyxNQUFNLENBQUM7SUFDekMsQ0FBQztTQUFNLENBQUM7UUFDTixNQUFNLElBQUkscUJBQVUsQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFDRCxPQUFPLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRSxTQUFTLEVBQUUsR0FBRyxDQUFDLFNBQVMsRUFBRSxDQUFDO0FBQzVELENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLG1CQUFtQixDQUFDLGNBQXNCO0lBQ3hELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDL0MsT0FBTyxXQUFXLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzVDLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLDJCQUEyQixDQUFDLGNBQW1CO0lBQzdELElBQUksT0FBTyxjQUFjLEtBQUssUUFBUSxJQUFJLENBQUMsVUFBVSxDQUFDLGNBQWMsQ0FBQyxJQUFJLG1CQUFtQixDQUFDLGNBQWMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUM5RyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLEtBQUssQ0FBQyxNQUEyQjtJQUMvQyxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ2xDLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxLQUFlLEVBQUUsTUFBYSxFQUFFLFFBQWlCO0lBQ2hGLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDNUIsSUFBSSxJQUFJLElBQUksU0FBUyxFQUFFLENBQUM7WUFDdEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDcEUsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0lBRUgsTUFBTSxRQUFRLEdBQUcsSUFBSSxnQkFBUSxFQUFFLENBQUM7SUFDaEMsSUFBSSxJQUFJLENBQUM7SUFDVCxJQUFJLENBQUM7UUFDSCxJQUFJLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDWCxNQUFNLElBQUkscUJBQVUsQ0FBQyx3REFBd0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDcEcsQ0FBQztJQUNELElBQUksUUFBUSxFQUFFLENBQUM7UUFDYixPQUFPLElBQUEsaUJBQVMsRUFBQyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDMUQsQ0FBQztTQUFNLENBQUM7UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ25DLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxLQUFlLEVBQUUsSUFBWTtJQUM1RCxNQUFNLFFBQVEsR0FBRyxJQUFJLGdCQUFRLEVBQUUsQ0FBQztJQUNoQyxJQUFJLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEMsT0FBTyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFO1FBQzdELElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLFNBQVM7WUFBRSxHQUFHLEdBQUcsY0FBYyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbEYsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNkLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ1QsQ0FBQztBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsU0FBZ0Isa0JBQWtCLENBQ2hDLFVBT0ksRUFBRTtJQUVOLElBQUksQ0FBQztRQUNILHVEQUF1RDtRQUN2RCxJQUFJLGtCQUFrQixHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUM7UUFDMUMsSUFBSSxPQUFPLENBQUMsUUFBUSxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3BELGtCQUFrQixHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7Z0JBQ3JELHVDQUF1QztnQkFDdkMsSUFBSSxRQUFRLENBQUMsU0FBUyxFQUFFLFFBQVEsS0FBSywrQ0FBK0MsRUFBRSxDQUFDO29CQUNyRixNQUFNLGFBQWEsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLEtBQVksQ0FBQztvQkFFdEQsc0NBQXNDO29CQUN0QyxNQUFNLGdCQUFnQixHQUFRLEVBQUUsQ0FBQztvQkFFakMsd0NBQXdDO29CQUN4QyxJQUFJLGFBQWEsQ0FBQyxhQUFhLEVBQUUsQ0FBQzt3QkFDaEMsZ0JBQWdCLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FBQztvQkFDbEYsQ0FBQztvQkFFRCxxQ0FBcUM7b0JBQ3JDLElBQUksYUFBYSxDQUFDLFVBQVUsRUFBRSxDQUFDO3dCQUM3QixnQkFBZ0IsQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO29CQUM1RSxDQUFDO29CQUVELGlDQUFpQztvQkFDakMsSUFBSSxhQUFhLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO3dCQUN2QyxnQkFBZ0IsQ0FBQyxNQUFNLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQztvQkFDakQsQ0FBQztvQkFFRCxxQ0FBcUM7b0JBQ3JDLE1BQU0sZUFBZSxHQUFHLGVBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztvQkFDcEYsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7b0JBRXBFLE9BQU87d0JBQ0wsR0FBRyxRQUFRO3dCQUNYLFNBQVMsRUFBRTs0QkFDVCxHQUFHLFFBQVEsQ0FBQyxTQUFTOzRCQUNyQixLQUFLLEVBQUUsV0FBVzt5QkFDbkI7cUJBQ0ssQ0FBQztnQkFDWCxDQUFDO2dCQUVELE9BQU8sUUFBUSxDQUFDO1lBQ2xCLENBQUMsQ0FBb0MsQ0FBQztRQUN4QyxDQUFDO1FBRUQseURBQXlEO1FBQ3pELE1BQU0sS0FBSyxHQUE4QjtZQUN2QyxRQUFRLEVBQUUsa0JBQWtCO1lBQzVCLGFBQWEsRUFBRSxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVM7WUFDNUYsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUztZQUN6RixVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVU7WUFDOUIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTO1lBQzVCLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtTQUMzQixDQUFDO1FBRUYsNENBQTRDO1FBQzVDLE1BQU0sWUFBWSxHQUFHLGVBQVEsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUVyRSx3QkFBd0I7UUFDeEIsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNYLE1BQU0sSUFBSSxxQkFBVSxDQUFDLG1DQUFtQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4RSxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCAqIGFzIGhleCBmcm9tICdAc3RhYmxlbGliL2hleCc7XG5pbXBvcnQgKiBhcyB0cm9ud2ViIGZyb20gJ3Ryb253ZWInO1xuaW1wb3J0IHsgcHJvdG9jb2wgfSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvcHJvdG9idWYvdHJvbic7XG5cbmltcG9ydCB7IFV0aWxzRXJyb3IgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBUcm9uRXJjMjBDb2luLCBjb2lucyB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IHtcbiAgVHJhbnNmZXJDb250cmFjdCxcbiAgUmF3RGF0YSxcbiAgQWNjb3VudFBlcm1pc3Npb25VcGRhdGVDb250cmFjdCxcbiAgVHJhbnNhY3Rpb25SZWNlaXB0LFxuICBQZXJtaXNzaW9uLFxuICBUcmlnZ2VyU21hcnRDb250cmFjdCxcbiAgRnJlZXplQmFsYW5jZUNvbnRyYWN0UGFyYW1ldGVyLFxuICBWb3RlV2l0bmVzc0NvbnRyYWN0UGFyYW1ldGVyLFxuICBGcmVlemVDb250cmFjdERlY29kZWQsXG4gIFZvdGVDb250cmFjdERlY29kZWQsXG4gIFVuZnJlZXplQmFsYW5jZUNvbnRyYWN0UGFyYW1ldGVyLFxuICBXaXRoZHJhd0V4cGlyZVVuZnJlZXplQ29udHJhY3RQYXJhbWV0ZXIsXG4gIFVuZnJlZXplQ29udHJhY3REZWNvZGVkLFxuICBXaXRoZHJhd0NvbnRyYWN0RGVjb2RlZCxcbiAgUmVzb3VyY2VNYW5hZ2VtZW50Q29udHJhY3RQYXJhbWV0ZXIsXG4gIFJlc291cmNlTWFuYWdlbWVudENvbnRyYWN0RGVjb2RlZCxcbn0gZnJvbSAnLi9pZmFjZSc7XG5pbXBvcnQgeyBDb250cmFjdFR5cGUsIFBlcm1pc3Npb25UeXBlLCBUcm9uUmVzb3VyY2UgfSBmcm9tICcuL2VudW0nO1xuaW1wb3J0IHsgQWJpQ29kZXIsIGhleENvbmNhdCB9IGZyb20gJ2V0aGVycy9saWIvdXRpbHMnO1xuaW1wb3J0IHsgREVMRUdBVElPTl9UWVBFX1VSTCB9IGZyb20gJy4vY29uc3RhbnRzJztcblxuZXhwb3J0IGNvbnN0IFRSQU5TQUNUSU9OX01BWF9FWFBJUkFUSU9OID0gODY0MDAwMDA7IC8vIG9uZSBkYXlcbmV4cG9ydCBjb25zdCBUUkFOU0FDVElPTl9ERUZBVUxUX0VYUElSQVRJT04gPSAzNjAwMDAwOyAvLyBvbmUgaG91clxuY29uc3QgQUREUkVTU19QUkVGSVhfUkVHRVggPSAvXig0MSkvO1xuY29uc3QgQUREUkVTU19QUkVGSVggPSAnNDEnO1xuXG5leHBvcnQgdHlwZSBCeXRlc0xpa2UgPSBudW1iZXJbXSB8IFVpbnQ4QXJyYXk7XG5cbmNvbnN0IGdldFRyb25Ub2tlbnMgPSAobmV0d29yayA9ICdtYWlubmV0JykgPT4ge1xuICByZXR1cm4gKFxuICAgIGNvaW5zXG4gICAgICAuZmlsdGVyKChjb2luKSA9PiBjb2luLmZhbWlseSA9PT0gJ3RyeCcpXG4gICAgICAuZmlsdGVyKCh0cngpID0+IHRyeC5uZXR3b3JrLnR5cGUgPT09IG5ldHdvcmsgJiYgdHJ4LmlzVG9rZW4pIGFzIHVua25vd24gYXMgVHJvbkVyYzIwQ29pbltdXG4gICkubWFwKChjb2lucykgPT4gY29pbnMuY29udHJhY3RBZGRyZXNzLnRvU3RyaW5nKCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IHRva2VuTWFpbm5ldENvbnRyYWN0QWRkcmVzc2VzID0gZ2V0VHJvblRva2VucygnbWFpbm5ldCcpO1xuZXhwb3J0IGNvbnN0IHRva2VuVGVzdG5ldENvbnRyYWN0QWRkcmVzc2VzID0gZ2V0VHJvblRva2VucygndGVzdG5ldCcpO1xuLyoqXG4gKiBUcm9uLXNwZWNpZmljIGhlbHBlciBmdW5jdGlvbnNcbiAqL1xuZXhwb3J0IHR5cGUgQnl0ZUFycmF5ID0gbnVtYmVyW107XG5leHBvcnQgdHlwZSBUcm9uQmluYXJ5TGlrZSA9IEJ5dGVBcnJheSB8IEJ1ZmZlciB8IFVpbnQ4QXJyYXkgfCBzdHJpbmc7XG5cbmV4cG9ydCBjb25zdCBWQUxJRF9SRVNPVVJDRV9UWVBFUyA9IFsnRU5FUkdZJywgJ0JBTkRXSURUSCddO1xuXG4vKipcbiAqIEBwYXJhbSBhZGRyZXNzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Jhc2U1OEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiB0cm9ud2ViLnV0aWxzLmNyeXB0by5pc0FkZHJlc3NWYWxpZChhZGRyZXNzKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gc3RyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRCeXRlQXJyYXlGcm9tSGV4QWRkcmVzcyhzdHI6IHN0cmluZyk6IEJ5dGVBcnJheSB7XG4gIHJldHVybiB0cm9ud2ViLnV0aWxzLmNvZGUuaGV4U3RyMmJ5dGVBcnJheShzdHIucmVwbGFjZSgnMHgnLCAnJykpO1xufVxuXG4vKipcbiAqIEBwYXJhbSBhcnJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEhleEFkZHJlc3NGcm9tQnl0ZUFycmF5KGFycjogQnl0ZUFycmF5KTogc3RyaW5nIHtcbiAgcmV0dXJuIHRyb253ZWIudXRpbHMuY29kZS5ieXRlQXJyYXkyaGV4U3RyKGFycik7XG59XG5cbi8qKlxuICogQHBhcmFtIG1lc3NhZ2VUb1ZlcmlmeVxuICogQHBhcmFtIGJhc2U1OEFkZHJlc3NcbiAqIEBwYXJhbSBzaWdIZXhcbiAqIEBwYXJhbSB1c2VUcm9uSGVhZGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2ZXJpZnlTaWduYXR1cmUoXG4gIG1lc3NhZ2VUb1ZlcmlmeTogc3RyaW5nLFxuICBiYXNlNThBZGRyZXNzOiBzdHJpbmcsXG4gIHNpZ0hleDogc3RyaW5nLFxuICB1c2VUcm9uSGVhZGVyID0gdHJ1ZVxuKTogYm9vbGVhbiB7XG4gIGlmICghaXNWYWxpZEhleChzaWdIZXgpKSB7XG4gICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ3NpZ25hdHVyZSBpcyBub3QgaW4gYSB2YWxpZCBmb3JtYXQsIG5lZWRzIHRvIGJlIGhleGFkZWNpbWFsJyk7XG4gIH1cblxuICBpZiAoIWlzVmFsaWRIZXgobWVzc2FnZVRvVmVyaWZ5KSkge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdtZXNzYWdlIGlzIG5vdCBpbiBhIHZhbGlkIGZvcm1hdCwgbmVlZHMgdG8gYmUgaGV4YWRlY2ltYWwnKTtcbiAgfVxuXG4gIGlmICghaXNCYXNlNThBZGRyZXNzKGJhc2U1OEFkZHJlc3MpKSB7XG4gICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ2FkZHJlc3MgbmVlZHMgdG8gYmUgYmFzZTU4IGVuY29kZWQnKTtcbiAgfVxuXG4gIHJldHVybiB0cm9ud2ViLlRyeC52ZXJpZnlTaWduYXR1cmUobWVzc2FnZVRvVmVyaWZ5LCBiYXNlNThBZGRyZXNzLCBzaWdIZXgsIHVzZVRyb25IZWFkZXIpO1xufVxuXG4vKipcbiAqIEBwYXJhbSBiYXNlNThcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEhleEFkZHJlc3NGcm9tQmFzZTU4QWRkcmVzcyhiYXNlNTg6IHN0cmluZyk6IHN0cmluZyB7XG4gIC8vIHB1bGxlZCBmcm9tOiBodHRwczovL2dpdGh1Yi5jb20vVFJPTi1VUy90cm9ud2ViL2Jsb2IvZGNiOGVmYTM2YTVlYmI2NWM0ZGFiMzYyNmU5MDI1NmE0NTNmM2IwZC9zcmMvdXRpbHMvaGVscC5qcyNMMTdcbiAgLy8gYnV0IHRoZXkgZG9uJ3Qgc3VyZmFjZSB0aGlzIGNhbGwgaW4gaW5kZXguanNcbiAgY29uc3QgYnl0ZXMgPSB0cm9ud2ViLnV0aWxzLmNyeXB0by5kZWNvZGVCYXNlNThBZGRyZXNzKGJhc2U1OCk7XG4gIC8vIEVuc3VyZSBieXRlcyBpcyBhIEJ5dGVBcnJheSAobnVtYmVyW10pXG4gIGlmIChBcnJheS5pc0FycmF5KGJ5dGVzKSkge1xuICAgIHJldHVybiBnZXRIZXhBZGRyZXNzRnJvbUJ5dGVBcnJheShieXRlcyk7XG4gIH1cbiAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ0ZhaWxlZCB0byBkZWNvZGUgYmFzZTU4IGFkZHJlc3MgdG8gYnl0ZSBhcnJheScpO1xufVxuLyoqXG4gKiBAcGFyYW0gcHJpdmF0ZUtleVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UHViS2V5RnJvbVByaUtleShwcml2YXRlS2V5OiBUcm9uQmluYXJ5TGlrZSk6IEJ5dGVBcnJheSB7XG4gIHJldHVybiB0cm9ud2ViLnV0aWxzLmNyeXB0by5nZXRQdWJLZXlGcm9tUHJpS2V5KHByaXZhdGVLZXkgYXMgQnl0ZXNMaWtlKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gcHJpdmF0ZUtleVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWRkcmVzc0Zyb21QcmlLZXkocHJpdmF0ZUtleTogVHJvbkJpbmFyeUxpa2UpOiBCeXRlQXJyYXkge1xuICByZXR1cm4gdHJvbndlYi51dGlscy5jcnlwdG8uZ2V0QWRkcmVzc0Zyb21QcmlLZXkocHJpdmF0ZUtleSBhcyBCeXRlc0xpa2UpO1xufVxuXG4vKipcbiAqIEBwYXJhbSBhZGRyZXNzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRCYXNlNThBZGRyZXNzRnJvbUJ5dGVBcnJheShhZGRyZXNzOiBCeXRlQXJyYXkpOiBzdHJpbmcge1xuICByZXR1cm4gdHJvbndlYi51dGlscy5jcnlwdG8uZ2V0QmFzZTU4Q2hlY2tBZGRyZXNzKGFkZHJlc3MpO1xufVxuXG4vKipcbiAqIEBwYXJhbSBoZXhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEJhc2U1OEFkZHJlc3NGcm9tSGV4KGhleDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgYXJyID0gZ2V0Qnl0ZUFycmF5RnJvbUhleEFkZHJlc3MoaGV4KTtcbiAgcmV0dXJuIGdldEJhc2U1OEFkZHJlc3NGcm9tQnl0ZUFycmF5KGFycik7XG59XG5cbi8qKlxuICogQHBhcmFtIHByaXZhdGVLZXlcbiAqIEBwYXJhbSB0cmFuc2FjdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gc2lnblRyYW5zYWN0aW9uKHByaXZhdGVLZXk6IHN0cmluZyB8IEJ5dGVBcnJheSwgdHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uUmVjZWlwdCk6IFRyYW5zYWN0aW9uUmVjZWlwdCB7XG4gIHJldHVybiB0cm9ud2ViLnV0aWxzLmNyeXB0by5zaWduVHJhbnNhY3Rpb24ocHJpdmF0ZUtleSwgdHJhbnNhY3Rpb24pIGFzIFRyYW5zYWN0aW9uUmVjZWlwdDtcbn1cblxuLyoqXG4gKiBAcGFyYW0gbWVzc2FnZVxuICogQHBhcmFtIHByaXZhdGVLZXlcbiAqIEBwYXJhbSB1c2VUcm9uSGVhZGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaWduU3RyaW5nKG1lc3NhZ2U6IHN0cmluZywgcHJpdmF0ZUtleTogc3RyaW5nIHwgQnl0ZUFycmF5LCB1c2VUcm9uSGVhZGVyID0gdHJ1ZSk6IHN0cmluZyB7XG4gIHJldHVybiB0cm9ud2ViLlRyeC5zaWduU3RyaW5nKG1lc3NhZ2UsIHByaXZhdGVLZXkgYXMgc3RyaW5nLCB1c2VUcm9uSGVhZGVyKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gcHViQnl0ZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFJhd0FkZHJlc3NGcm9tUHViS2V5KHB1YkJ5dGVzOiBUcm9uQmluYXJ5TGlrZSk6IEJ5dGVBcnJheSB7XG4gIHJldHVybiB0cm9ud2ViLnV0aWxzLmNyeXB0by5jb21wdXRlQWRkcmVzcyhwdWJCeXRlcyBhcyBCeXRlc0xpa2UpO1xufVxuXG4vKipcbiAqIERlY29kZXMgYSBoZXggZW5jb2RlZCB0cmFuc2FjdGlvbiBpbiBpdHMgcHJvdG9idWYgcmVwcmVzZW50YXRpb24uXG4gKlxuICogQHBhcmFtIGhleFN0cmluZyByYXdfZGF0YV9oZXggZmllbGQgZnJvbSB0cm9uIHRyYW5zYWN0aW9uc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlVHJhbnNhY3Rpb24oaGV4U3RyaW5nOiBzdHJpbmcpOiBSYXdEYXRhIHtcbiAgY29uc3QgcmF3VHJhbnNhY3Rpb24gPSBkZWNvZGVSYXdUcmFuc2FjdGlvbihoZXhTdHJpbmcpO1xuXG4gIC8vIHRoZXJlIHNob3VsZCBub3QgYmUgbXVsdGlwbGUgY29udHJhY3RzIGluIHRoaXMgZGF0YVxuICBpZiAocmF3VHJhbnNhY3Rpb24uY29udHJhY3RzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdOdW1iZXIgb2YgY29udHJhY3RzIGlzIGdyZWF0ZXIgdGhhbiAxLicpO1xuICB9XG5cbiAgbGV0IGNvbnRyYWN0OlxuICAgIHwgVHJhbnNmZXJDb250cmFjdFtdXG4gICAgfCBBY2NvdW50UGVybWlzc2lvblVwZGF0ZUNvbnRyYWN0W11cbiAgICB8IFRyaWdnZXJTbWFydENvbnRyYWN0W11cbiAgICB8IEZyZWV6ZUJhbGFuY2VDb250cmFjdFBhcmFtZXRlcltdXG4gICAgfCBWb3RlV2l0bmVzc0NvbnRyYWN0UGFyYW1ldGVyW11cbiAgICB8IFVuZnJlZXplQmFsYW5jZUNvbnRyYWN0UGFyYW1ldGVyW11cbiAgICB8IFdpdGhkcmF3RXhwaXJlVW5mcmVlemVDb250cmFjdFBhcmFtZXRlcltdXG4gICAgfCBSZXNvdXJjZU1hbmFnZW1lbnRDb250cmFjdFBhcmFtZXRlcltdO1xuXG4gIGxldCBjb250cmFjdFR5cGU6IENvbnRyYWN0VHlwZTtcblxuICAvLyBlbnN1cmUgdGhlIGNvbnRyYWN0IHR5cGUgaXMgc3VwcG9ydGVkXG4gIHN3aXRjaCAocmF3VHJhbnNhY3Rpb24uY29udHJhY3RzWzBdLnBhcmFtZXRlci50eXBlX3VybCkge1xuICAgIGNhc2UgJ3R5cGUuZ29vZ2xlYXBpcy5jb20vcHJvdG9jb2wuVHJhbnNmZXJDb250cmFjdCc6XG4gICAgICBjb250cmFjdFR5cGUgPSBDb250cmFjdFR5cGUuVHJhbnNmZXI7XG4gICAgICBjb250cmFjdCA9IGV4cG9ydHMuZGVjb2RlVHJhbnNmZXJDb250cmFjdChyYXdUcmFuc2FjdGlvbi5jb250cmFjdHNbMF0ucGFyYW1ldGVyLnZhbHVlKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3R5cGUuZ29vZ2xlYXBpcy5jb20vcHJvdG9jb2wuQWNjb3VudFBlcm1pc3Npb25VcGRhdGVDb250cmFjdCc6XG4gICAgICBjb250cmFjdFR5cGUgPSBDb250cmFjdFR5cGUuQWNjb3VudFBlcm1pc3Npb25VcGRhdGU7XG4gICAgICBjb250cmFjdCA9IGV4cG9ydHMuZGVjb2RlQWNjb3VudFBlcm1pc3Npb25VcGRhdGVDb250cmFjdChyYXdUcmFuc2FjdGlvbi5jb250cmFjdHNbMF0ucGFyYW1ldGVyLnZhbHVlKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3R5cGUuZ29vZ2xlYXBpcy5jb20vcHJvdG9jb2wuVHJpZ2dlclNtYXJ0Q29udHJhY3QnOlxuICAgICAgY29udHJhY3RUeXBlID0gQ29udHJhY3RUeXBlLlRyaWdnZXJTbWFydENvbnRyYWN0O1xuICAgICAgY29udHJhY3QgPSBleHBvcnRzLmRlY29kZVRyaWdnZXJTbWFydENvbnRyYWN0KHJhd1RyYW5zYWN0aW9uLmNvbnRyYWN0c1swXS5wYXJhbWV0ZXIudmFsdWUpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAndHlwZS5nb29nbGVhcGlzLmNvbS9wcm90b2NvbC5GcmVlemVCYWxhbmNlVjJDb250cmFjdCc6XG4gICAgICBjb250cmFjdFR5cGUgPSBDb250cmFjdFR5cGUuRnJlZXplQmFsYW5jZVYyO1xuICAgICAgY29udHJhY3QgPSBkZWNvZGVGcmVlemVCYWxhbmNlVjJDb250cmFjdChyYXdUcmFuc2FjdGlvbi5jb250cmFjdHNbMF0ucGFyYW1ldGVyLnZhbHVlKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3R5cGUuZ29vZ2xlYXBpcy5jb20vcHJvdG9jb2wuVm90ZVdpdG5lc3NDb250cmFjdCc6XG4gICAgICBjb250cmFjdFR5cGUgPSBDb250cmFjdFR5cGUuVm90ZVdpdG5lc3M7XG4gICAgICBjb250cmFjdCA9IGRlY29kZVZvdGVXaXRuZXNzQ29udHJhY3QocmF3VHJhbnNhY3Rpb24uY29udHJhY3RzWzBdLnBhcmFtZXRlci52YWx1ZSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICd0eXBlLmdvb2dsZWFwaXMuY29tL3Byb3RvY29sLldpdGhkcmF3RXhwaXJlVW5mcmVlemVDb250cmFjdCc6XG4gICAgICBjb250cmFjdCA9IGRlY29kZVdpdGhkcmF3RXhwaXJlVW5mcmVlemVDb250cmFjdChyYXdUcmFuc2FjdGlvbi5jb250cmFjdHNbMF0ucGFyYW1ldGVyLnZhbHVlKTtcbiAgICAgIGNvbnRyYWN0VHlwZSA9IENvbnRyYWN0VHlwZS5XaXRoZHJhd0V4cGlyZVVuZnJlZXplO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAndHlwZS5nb29nbGVhcGlzLmNvbS9wcm90b2NvbC5XaXRoZHJhd0JhbGFuY2VDb250cmFjdCc6XG4gICAgICBjb250cmFjdCA9IGRlY29kZVdpdGhkcmF3QmFsYW5jZUNvbnRyYWN0KHJhd1RyYW5zYWN0aW9uLmNvbnRyYWN0c1swXS5wYXJhbWV0ZXIudmFsdWUpO1xuICAgICAgY29udHJhY3RUeXBlID0gQ29udHJhY3RUeXBlLldpdGhkcmF3QmFsYW5jZTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3R5cGUuZ29vZ2xlYXBpcy5jb20vcHJvdG9jb2wuVW5mcmVlemVCYWxhbmNlVjJDb250cmFjdCc6XG4gICAgICBjb250cmFjdCA9IGRlY29kZVVuZnJlZXplQmFsYW5jZVYyQ29udHJhY3QocmF3VHJhbnNhY3Rpb24uY29udHJhY3RzWzBdLnBhcmFtZXRlci52YWx1ZSk7XG4gICAgICBjb250cmFjdFR5cGUgPSBDb250cmFjdFR5cGUuVW5mcmVlemVCYWxhbmNlVjI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIERFTEVHQVRJT05fVFlQRV9VUkw6XG4gICAgICBjb250cmFjdFR5cGUgPSBDb250cmFjdFR5cGUuRGVsZWdhdGVSZXNvdXJjZUNvbnRyYWN0O1xuICAgICAgY29udHJhY3QgPSBkZWNvZGVEZWxlZ2F0ZVJlc291cmNlQ29udHJhY3QocmF3VHJhbnNhY3Rpb24uY29udHJhY3RzWzBdLnBhcmFtZXRlci52YWx1ZSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICd0eXBlLmdvb2dsZWFwaXMuY29tL3Byb3RvY29sLlVuRGVsZWdhdGVSZXNvdXJjZUNvbnRyYWN0JzpcbiAgICAgIGNvbnRyYWN0VHlwZSA9IENvbnRyYWN0VHlwZS5VbkRlbGVnYXRlUmVzb3VyY2VDb250cmFjdDtcbiAgICAgIGNvbnRyYWN0ID0gZGVjb2RlVW5EZWxlZ2F0ZVJlc291cmNlQ29udHJhY3QocmF3VHJhbnNhY3Rpb24uY29udHJhY3RzWzBdLnBhcmFtZXRlci52YWx1ZSk7XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ1Vuc3VwcG9ydGVkIGNvbnRyYWN0IHR5cGUnKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgY29udHJhY3RUeXBlLFxuICAgIGNvbnRyYWN0LFxuICAgIGV4cGlyYXRpb246IHJhd1RyYW5zYWN0aW9uLmV4cGlyYXRpb24sXG4gICAgdGltZXN0YW1wOiByYXdUcmFuc2FjdGlvbi50aW1lc3RhbXAsXG4gICAgcmVmX2Jsb2NrX2J5dGVzOiByYXdUcmFuc2FjdGlvbi5ibG9ja0J5dGVzLFxuICAgIHJlZl9ibG9ja19oYXNoOiByYXdUcmFuc2FjdGlvbi5ibG9ja0hhc2gsXG4gICAgZmVlX2xpbWl0OiArcmF3VHJhbnNhY3Rpb24uZmVlTGltaXQsXG4gIH07XG59XG5cbi8qKlxuICogRGVjb2RlcyBhIHRyYW5zYWN0aW9uJ3MgcmF3IGZpZWxkIGZyb20gYSBiYXNlNjQgZW5jb2RlZCBzdHJpbmcuIFRoaXMgaXMgYSBwcm90b2J1ZiByZXByZXNlbnRhdGlvbi5cbiAqXG4gKiBAcGFyYW0gaGV4U3RyaW5nIHRoaXMgaXMgdGhlIHJhdyBoZXhhZGVjaW1hbCBlbmNvZGVkIHN0cmluZy4gRG9jIGZvdW5kIGluIHRoZSBmb2xsb3dpbmcgbGluay5cbiAqIEBleGFtcGxlXG4gKiBAc2VlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vQml0R28vYml0Z28tYWNjb3VudC1saWIvYmxvYi81ZjI4MjU4ODcwMTc3OGE0NDIxYzc1ZmE2MWY0MjcxM2Y1NmU5NWI5L3Jlc291cmNlcy9wcm90b2J1Zi90cm9uLnByb3RvI0wzMTl9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVSYXdUcmFuc2FjdGlvbihoZXhTdHJpbmc6IHN0cmluZyk6IHtcbiAgZXhwaXJhdGlvbjogbnVtYmVyO1xuICB0aW1lc3RhbXA6IG51bWJlcjtcbiAgY29udHJhY3RzOiBBcnJheTxhbnk+O1xuICBibG9ja0J5dGVzOiBzdHJpbmc7XG4gIGJsb2NrSGFzaDogc3RyaW5nO1xuICBmZWVMaW1pdDogc3RyaW5nO1xufSB7XG4gIGNvbnN0IGJ5dGVzID0gQnVmZmVyLmZyb20oaGV4U3RyaW5nLCAnaGV4Jyk7XG5cbiAgbGV0IHJhdztcbiAgdHJ5IHtcbiAgICAvLyB3ZSBuZWVkIHRvIGRlY29kZSBvdXIgcmF3X2RhdGFfaGV4IGZpZWxkIGZpcnN0XG4gICAgcmF3ID0gcHJvdG9jb2wuVHJhbnNhY3Rpb24ucmF3LmRlY29kZShieXRlcyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignVGhlcmUgd2FzIGFuIGVycm9yIGRlY29kaW5nIHRoZSBpbml0aWFsIHJhd19kYXRhX2hleCBmcm9tIHRoZSBzZXJpYWxpemVkIHR4LicpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBleHBpcmF0aW9uOiBOdW1iZXIocmF3LmV4cGlyYXRpb24pLFxuICAgIHRpbWVzdGFtcDogTnVtYmVyKHJhdy50aW1lc3RhbXApLFxuICAgIGNvbnRyYWN0czogcmF3LmNvbnRyYWN0LFxuICAgIGJsb2NrQnl0ZXM6IHRvSGV4KHJhdy5yZWZCbG9ja0J5dGVzKSxcbiAgICBmZWVMaW1pdDogcmF3LmZlZUxpbWl0LFxuICAgIGJsb2NrSGFzaDogdG9IZXgocmF3LnJlZkJsb2NrSGFzaCksXG4gIH07XG59XG5cbi8qKlxuICogQ29udmVydHMgYSBiYXNlNjQgZW5jb2RlZCBzdHJpbmcgdG8gaGV4XG4gKlxuICogQHBhcmFtIGJhc2U2NCAtIFRoZSBiYXNlNjQgZW5jb2RlZCBzdHJpbmcgdG8gY29udmVydFxuICogQHJldHVybnMge3N0cmluZ30gLSBUaGUgaGV4IHJlcHJlc2VudGF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRIZXhGcm9tQmFzZTY0KGJhc2U2NDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgYnVmZmVyID0gQnVmZmVyLmZyb20oYmFzZTY0LCAnYmFzZTY0Jyk7XG4gIHJldHVybiBidWZmZXIudG9TdHJpbmcoJ2hleCcpO1xufVxuXG4vKipcbiAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSBwYXNzZWQgc3RyaW5nIGlzIGEgc2FmZSBoZXggc3RyaW5nIGZvciB0cm9uJ3MgcHVycG9zZXMuXG4gKlxuICogQHBhcmFtIGhleCBBIHZhbGlkIGhleCBzdHJpbmcgbXVzdCBiZSBhIHN0cmluZyBtYWRlIG9mIG51bWJlcnMgYW5kIGNoYXJhY3RlcnMgYW5kIGhhcyBhbiBldmVuIGxlbmd0aC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRIZXgoaGV4OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIC9eKDB4KT8oWzAtOWEtZl17Mn0pKyQvaS50ZXN0KGhleCk7XG59XG5cbi8qKiBEZXNlcmlhbGl6ZSB0aGUgc2VnbWVudCBvZiB0aGUgdHhIZXggd2hpY2ggY29ycmVzcG9uZHMgd2l0aCB0aGUgZGV0YWlscyBvZiB0aGUgdHJhbnNmZXJcbiAqXG4gKiBAcGFyYW0gdHJhbnNmZXJIZXggaXMgdGhlIHZhbHVlIHByb3BlcnR5IG9mIHRoZSBcInBhcmFtZXRlclwiIGZpZWxkIG9mIGNvbnRyYWN0TGlzdFswXVxuICogKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVUcmFuc2ZlckNvbnRyYWN0KHRyYW5zZmVySGV4OiBzdHJpbmcpOiBUcmFuc2ZlckNvbnRyYWN0W10ge1xuICBjb25zdCBjb250cmFjdEJ5dGVzID0gQnVmZmVyLmZyb20odHJhbnNmZXJIZXgsICdiYXNlNjQnKTtcbiAgbGV0IHRyYW5zZmVyQ29udHJhY3Q7XG5cbiAgdHJ5IHtcbiAgICB0cmFuc2ZlckNvbnRyYWN0ID0gcHJvdG9jb2wuVHJhbnNmZXJDb250cmFjdC5kZWNvZGUoY29udHJhY3RCeXRlcyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignVGhlcmUgd2FzIGFuIGVycm9yIGRlY29kaW5nIHRoZSB0cmFuc2ZlciBjb250cmFjdCBpbiB0aGUgdHJhbnNhY3Rpb24uJyk7XG4gIH1cblxuICBpZiAoIXRyYW5zZmVyQ29udHJhY3Qub3duZXJBZGRyZXNzKSB7XG4gICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ093bmVyIGFkZHJlc3MgZG9lcyBub3QgZXhpc3QgaW4gdGhpcyB0cmFuc2ZlciBjb250cmFjdC4nKTtcbiAgfVxuXG4gIGlmICghdHJhbnNmZXJDb250cmFjdC50b0FkZHJlc3MpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignRGVzdGluYXRpb24gYWRkcmVzcyBkb2VzIG5vdCBleGlzdCBpbiB0aGlzIHRyYW5zZmVyIGNvbnRyYWN0LicpO1xuICB9XG5cbiAgaWYgKCF0cmFuc2ZlckNvbnRyYWN0Lmhhc093blByb3BlcnR5KCdhbW91bnQnKSkge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdBbW91bnQgZG9lcyBub3QgZXhpc3QgaW4gdGhpcyB0cmFuc2ZlciBjb250cmFjdC4nKTtcbiAgfVxuXG4gIC8vIGRlc2VyaWFsaXplIGF0dHJpYnV0ZXNcbiAgY29uc3Qgb3duZXJfYWRkcmVzcyA9IGdldEJhc2U1OEFkZHJlc3NGcm9tQnl0ZUFycmF5KFxuICAgIGdldEJ5dGVBcnJheUZyb21IZXhBZGRyZXNzKEJ1ZmZlci5mcm9tKHRyYW5zZmVyQ29udHJhY3Qub3duZXJBZGRyZXNzLCAnYmFzZTY0JykudG9TdHJpbmcoJ2hleCcpKVxuICApO1xuICBjb25zdCB0b19hZGRyZXNzID0gZ2V0QmFzZTU4QWRkcmVzc0Zyb21CeXRlQXJyYXkoXG4gICAgZ2V0Qnl0ZUFycmF5RnJvbUhleEFkZHJlc3MoQnVmZmVyLmZyb20odHJhbnNmZXJDb250cmFjdC50b0FkZHJlc3MsICdiYXNlNjQnKS50b1N0cmluZygnaGV4JykpXG4gICk7XG4gIGNvbnN0IGFtb3VudCA9IHRyYW5zZmVyQ29udHJhY3QuYW1vdW50O1xuXG4gIHJldHVybiBbXG4gICAge1xuICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgYW1vdW50OiBOdW1iZXIoYW1vdW50KSxcbiAgICAgICAgICBvd25lcl9hZGRyZXNzLFxuICAgICAgICAgIHRvX2FkZHJlc3MsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIF07XG59XG5cbi8qKlxuICogRGVzZXJpYWxpemUgdGhlIHNlZ21lbnQgb2YgdGhlIHR4SGV4IGNvcnJlc3BvbmRpbmcgd2l0aCB0cmlnZ2VyIHNtYXJ0IGNvbnRyYWN0XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGJhc2U2NFxuICogQHJldHVybnMge0FjY291bnRQZXJtaXNzaW9uVXBkYXRlQ29udHJhY3R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVUcmlnZ2VyU21hcnRDb250cmFjdChiYXNlNjQ6IHN0cmluZyk6IFRyaWdnZXJTbWFydENvbnRyYWN0W10ge1xuICBsZXQgY29udHJhY3RDYWxsRGVjb2RlZDtcbiAgdHJ5IHtcbiAgICBjb250cmFjdENhbGxEZWNvZGVkID0gcHJvdG9jb2wuVHJpZ2dlclNtYXJ0Q29udHJhY3QuZGVjb2RlKEJ1ZmZlci5mcm9tKGJhc2U2NCwgJ2Jhc2U2NCcpKS50b0pTT04oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdUaGVyZSB3YXMgYW4gZXJyb3IgZGVjb2RpbmcgdGhlIGNvbnRyYWN0IGNhbGwgaW4gdGhlIHRyYW5zYWN0aW9uLicpO1xuICB9XG5cbiAgaWYgKCFjb250cmFjdENhbGxEZWNvZGVkLm93bmVyQWRkcmVzcykge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdPd25lciBhZGRyZXNzIGRvZXMgbm90IGV4aXN0IGluIHRoaXMgY29udHJhY3QgY2FsbC4nKTtcbiAgfVxuXG4gIGlmICghY29udHJhY3RDYWxsRGVjb2RlZC5jb250cmFjdEFkZHJlc3MpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignRGVzdGluYXRpb24gY29udHJhY3QgYWRkcmVzcyBkb2VzIG5vdCBleGlzdCBpbiB0aGlzIGNvbnRyYWN0IGNhbGwuJyk7XG4gIH1cblxuICBpZiAoIWNvbnRyYWN0Q2FsbERlY29kZWQuZGF0YSkge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdEYXRhIGRvZXMgbm90IGV4aXN0IGluIHRoaXMgY29udHJhY3QgY2FsbC4nKTtcbiAgfVxuXG4gIC8vIGRlc2VyaWFsaXplIGF0dHJpYnV0ZXNcbiAgY29uc3Qgb3duZXJfYWRkcmVzcyA9IGdldEJhc2U1OEFkZHJlc3NGcm9tQnl0ZUFycmF5KFxuICAgIGdldEJ5dGVBcnJheUZyb21IZXhBZGRyZXNzKEJ1ZmZlci5mcm9tKGNvbnRyYWN0Q2FsbERlY29kZWQub3duZXJBZGRyZXNzLCAnYmFzZTY0JykudG9TdHJpbmcoJ2hleCcpKVxuICApO1xuICBjb25zdCBjb250cmFjdF9hZGRyZXNzID0gZ2V0QmFzZTU4QWRkcmVzc0Zyb21CeXRlQXJyYXkoXG4gICAgZ2V0Qnl0ZUFycmF5RnJvbUhleEFkZHJlc3MoQnVmZmVyLmZyb20oY29udHJhY3RDYWxsRGVjb2RlZC5jb250cmFjdEFkZHJlc3MsICdiYXNlNjQnKS50b1N0cmluZygnaGV4JykpXG4gICk7XG4gIGNvbnN0IGRhdGEgPSBjb250cmFjdENhbGxEZWNvZGVkLmRhdGE7XG4gIHJldHVybiBbXG4gICAge1xuICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICBvd25lcl9hZGRyZXNzLFxuICAgICAgICAgIGNvbnRyYWN0X2FkZHJlc3MsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIF07XG59XG5cbi8qKlxuICogRGVzZXJpYWxpemUgdGhlIHNlZ21lbnQgb2YgdGhlIHR4SGV4IGNvcnJlc3BvbmRpbmcgd2l0aCB0aGUgZGV0YWlscyBvZiB0aGUgY29udHJhY3Qgd2hpY2ggdXBkYXRlc1xuICogYWNjb3VudCBwZXJtaXNzaW9uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGJhc2U2NFxuICogQHJldHVybnMge0FjY291bnRQZXJtaXNzaW9uVXBkYXRlQ29udHJhY3R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVBY2NvdW50UGVybWlzc2lvblVwZGF0ZUNvbnRyYWN0KGJhc2U2NDogc3RyaW5nKTogQWNjb3VudFBlcm1pc3Npb25VcGRhdGVDb250cmFjdCB7XG4gIGNvbnN0IGFjY291bnRVcGRhdGVDb250cmFjdCA9IHByb3RvY29sLkFjY291bnRQZXJtaXNzaW9uVXBkYXRlQ29udHJhY3QuZGVjb2RlKEJ1ZmZlci5mcm9tKGJhc2U2NCwgJ2Jhc2U2NCcpKS50b0pTT04oKTtcbiAgYXNzZXJ0KGFjY291bnRVcGRhdGVDb250cmFjdC5vd25lckFkZHJlc3MpO1xuICBhc3NlcnQoYWNjb3VudFVwZGF0ZUNvbnRyYWN0Lm93bmVyKTtcbiAgYXNzZXJ0KGFjY291bnRVcGRhdGVDb250cmFjdC5oYXNPd25Qcm9wZXJ0eSgnYWN0aXZlcycpKTtcblxuICBjb25zdCBvd25lckFkZHJlc3MgPSBnZXRCYXNlNThBZGRyZXNzRnJvbUJ5dGVBcnJheShcbiAgICBnZXRCeXRlQXJyYXlGcm9tSGV4QWRkcmVzcyhCdWZmZXIuZnJvbShhY2NvdW50VXBkYXRlQ29udHJhY3Qub3duZXJBZGRyZXNzLCAnYmFzZTY0JykudG9TdHJpbmcoJ2hleCcpKVxuICApO1xuICBjb25zdCBvd25lcjogUGVybWlzc2lvbiA9IGNyZWF0ZVBlcm1pc3Npb24oYWNjb3VudFVwZGF0ZUNvbnRyYWN0Lm93bmVyKTtcbiAgbGV0IHdpdG5lc3M6IFBlcm1pc3Npb24gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gIGlmIChhY2NvdW50VXBkYXRlQ29udHJhY3Qud2l0bmVzcykge1xuICAgIHdpdG5lc3MgPSBjcmVhdGVQZXJtaXNzaW9uKGFjY291bnRVcGRhdGVDb250cmFjdC53aXRuZXNzKTtcbiAgfVxuICBjb25zdCBhY3RpdmVMaXN0ID0gYWNjb3VudFVwZGF0ZUNvbnRyYWN0LmFjdGl2ZXMubWFwKChhY3RpdmUpID0+IGNyZWF0ZVBlcm1pc3Npb24oYWN0aXZlKSk7XG5cbiAgcmV0dXJuIHtcbiAgICBvd25lckFkZHJlc3MsXG4gICAgb3duZXIsXG4gICAgd2l0bmVzcyxcbiAgICBhY3RpdmVzOiBhY3RpdmVMaXN0LFxuICB9O1xufVxuXG4vKipcbiAqIERlc2VyaWFsaXplIHRoZSBzZWdtZW50IG9mIHRoZSB0eEhleCBjb3JyZXNwb25kaW5nIHdpdGggZnJlZXplIGJhbGFuY2UgY29udHJhY3RcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gYmFzZTY0IC0gVGhlIGJhc2U2NCBlbmNvZGVkIGNvbnRyYWN0IGRhdGFcbiAqIEByZXR1cm5zIHtGcmVlemVCYWxhbmNlQ29udHJhY3RQYXJhbWV0ZXJbXX0gLSBBcnJheSBjb250YWluaW5nIHRoZSBkZWNvZGVkIGZyZWV6ZSBjb250cmFjdFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlRnJlZXplQmFsYW5jZVYyQ29udHJhY3QoYmFzZTY0OiBzdHJpbmcpOiBGcmVlemVCYWxhbmNlQ29udHJhY3RQYXJhbWV0ZXJbXSB7XG4gIGxldCBmcmVlemVDb250cmFjdDogRnJlZXplQ29udHJhY3REZWNvZGVkO1xuICB0cnkge1xuICAgIGZyZWV6ZUNvbnRyYWN0ID0gcHJvdG9jb2wuRnJlZXplQmFsYW5jZVYyQ29udHJhY3QuZGVjb2RlKEJ1ZmZlci5mcm9tKGJhc2U2NCwgJ2Jhc2U2NCcpKS50b0pTT04oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdUaGVyZSB3YXMgYW4gZXJyb3IgZGVjb2RpbmcgdGhlIGZyZWV6ZSBjb250cmFjdCBpbiB0aGUgdHJhbnNhY3Rpb24uJyk7XG4gIH1cblxuICBpZiAoIWZyZWV6ZUNvbnRyYWN0Lm93bmVyQWRkcmVzcykge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdPd25lciBhZGRyZXNzIGRvZXMgbm90IGV4aXN0IGluIHRoaXMgZnJlZXplIGNvbnRyYWN0LicpO1xuICB9XG5cbiAgaWYgKGZyZWV6ZUNvbnRyYWN0LnJlc291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignUmVzb3VyY2UgdHlwZSBkb2VzIG5vdCBleGlzdCBpbiB0aGlzIGZyZWV6ZSBjb250cmFjdC4nKTtcbiAgfVxuXG4gIGlmIChmcmVlemVDb250cmFjdC5mcm96ZW5CYWxhbmNlID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignRnJvemVuIGJhbGFuY2UgZG9lcyBub3QgZXhpc3QgaW4gdGhpcyBmcmVlemUgY29udHJhY3QuJyk7XG4gIH1cblxuICBjb25zdCBvd25lcl9hZGRyZXNzID0gZ2V0QmFzZTU4QWRkcmVzc0Zyb21CeXRlQXJyYXkoXG4gICAgZ2V0Qnl0ZUFycmF5RnJvbUhleEFkZHJlc3MoQnVmZmVyLmZyb20oZnJlZXplQ29udHJhY3Qub3duZXJBZGRyZXNzLCAnYmFzZTY0JykudG9TdHJpbmcoJ2hleCcpKVxuICApO1xuXG4gIGNvbnN0IHJlc291cmNlVmFsdWUgPSBmcmVlemVDb250cmFjdC5yZXNvdXJjZSA9PT0gMCA/IFRyb25SZXNvdXJjZS5CQU5EV0lEVEggOiBUcm9uUmVzb3VyY2UuRU5FUkdZO1xuXG4gIHJldHVybiBbXG4gICAge1xuICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgcmVzb3VyY2U6IHJlc291cmNlVmFsdWUsXG4gICAgICAgICAgZnJvemVuX2JhbGFuY2U6IE51bWJlcihmcmVlemVDb250cmFjdC5mcm96ZW5CYWxhbmNlKSxcbiAgICAgICAgICBvd25lcl9hZGRyZXNzLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICBdO1xufVxuXG4vKipcbiAqIERlc2VyaWFsaXplIHRoZSBzZWdtZW50IG9mIHRoZSB0eEhleCBjb3JyZXNwb25kaW5nIHdpdGggdm90ZSB3aXRuZXNzIGNvbnRyYWN0XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGJhc2U2NCAtIFRoZSBiYXNlNjQgZW5jb2RlZCBjb250cmFjdCBkYXRhXG4gKiBAcmV0dXJucyB7Vm90ZVdpdG5lc3NDb250cmFjdFBhcmFtZXRlcltdfSAtIEFycmF5IGNvbnRhaW5pbmcgdGhlIGRlY29kZWQgdm90ZSB3aXRuZXNzIGNvbnRyYWN0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVWb3RlV2l0bmVzc0NvbnRyYWN0KGJhc2U2NDogc3RyaW5nKTogVm90ZVdpdG5lc3NDb250cmFjdFBhcmFtZXRlcltdIHtcbiAgbGV0IHZvdGVDb250cmFjdDogVm90ZUNvbnRyYWN0RGVjb2RlZDtcbiAgdHJ5IHtcbiAgICB2b3RlQ29udHJhY3QgPSBwcm90b2NvbC5Wb3RlV2l0bmVzc0NvbnRyYWN0LmRlY29kZShCdWZmZXIuZnJvbShiYXNlNjQsICdiYXNlNjQnKSkudG9KU09OKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignVGhlcmUgd2FzIGFuIGVycm9yIGRlY29kaW5nIHRoZSB2b3RlIGNvbnRyYWN0IGluIHRoZSB0cmFuc2FjdGlvbi4nKTtcbiAgfVxuXG4gIGlmICghdm90ZUNvbnRyYWN0Lm93bmVyQWRkcmVzcykge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdPd25lciBhZGRyZXNzIGRvZXMgbm90IGV4aXN0IGluIHRoaXMgdm90ZSBjb250cmFjdC4nKTtcbiAgfVxuXG4gIGlmICghQXJyYXkuaXNBcnJheSh2b3RlQ29udHJhY3Qudm90ZXMpIHx8IHZvdGVDb250cmFjdC52b3Rlcy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignVm90ZXMgZG8gbm90IGV4aXN0IG9yIGFyZSBlbXB0eSBpbiB0aGlzIHZvdGUgY29udHJhY3QuJyk7XG4gIH1cblxuICAvLyBkZXNlcmlhbGl6ZSBhdHRyaWJ1dGVzXG4gIGNvbnN0IG93bmVyX2FkZHJlc3MgPSBnZXRCYXNlNThBZGRyZXNzRnJvbUJ5dGVBcnJheShcbiAgICBnZXRCeXRlQXJyYXlGcm9tSGV4QWRkcmVzcyhCdWZmZXIuZnJvbSh2b3RlQ29udHJhY3Qub3duZXJBZGRyZXNzLCAnYmFzZTY0JykudG9TdHJpbmcoJ2hleCcpKVxuICApO1xuXG4gIGludGVyZmFjZSBWb3RlSXRlbSB7XG4gICAgdm90ZUFkZHJlc3M/OiBzdHJpbmc7XG4gICAgdm90ZUNvdW50Pzogc3RyaW5nIHwgbnVtYmVyO1xuICB9XG5cbiAgY29uc3Qgdm90ZXMgPSB2b3RlQ29udHJhY3Qudm90ZXMubWFwKCh2b3RlOiBWb3RlSXRlbSkgPT4ge1xuICAgIGlmICghdm90ZS52b3RlQWRkcmVzcykge1xuICAgICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ1ZvdGUgYWRkcmVzcyBpcyBtaXNzaW5nIGluIG9uZSBvZiB0aGUgdm90ZXMuJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHZvdGVfYWRkcmVzczogZ2V0QmFzZTU4QWRkcmVzc0Zyb21CeXRlQXJyYXkoXG4gICAgICAgIGdldEJ5dGVBcnJheUZyb21IZXhBZGRyZXNzKEJ1ZmZlci5mcm9tKHZvdGUudm90ZUFkZHJlc3MsICdiYXNlNjQnKS50b1N0cmluZygnaGV4JykpXG4gICAgICApLFxuICAgICAgdm90ZV9jb3VudDogTnVtYmVyKHZvdGUudm90ZUNvdW50IHx8IDApLFxuICAgIH07XG4gIH0pO1xuXG4gIHJldHVybiBbXG4gICAge1xuICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgb3duZXJfYWRkcmVzcyxcbiAgICAgICAgICB2b3RlcyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgXTtcbn1cblxuLyoqXG4gKiBEZXNlcmlhbGl6ZSB0aGUgc2VnbWVudCBvZiB0aGUgdHhIZXggY29ycmVzcG9uZGluZyB3aXRoIHVuZnJlZXplIGJhbGFuY2UgY29udHJhY3RcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gYmFzZTY0IC0gVGhlIGJhc2U2NCBlbmNvZGVkIGNvbnRyYWN0IGRhdGFcbiAqIEByZXR1cm5zIHtVbmZyZWV6ZUJhbGFuY2VDb250cmFjdFBhcmFtZXRlcltdfSAtIEFycmF5IGNvbnRhaW5pbmcgdGhlIGRlY29kZWQgdW5mcmVlemUgY29udHJhY3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVVuZnJlZXplQmFsYW5jZVYyQ29udHJhY3QoYmFzZTY0OiBzdHJpbmcpOiBVbmZyZWV6ZUJhbGFuY2VDb250cmFjdFBhcmFtZXRlcltdIHtcbiAgbGV0IHVuZnJlZXplQ29udHJhY3Q6IFVuZnJlZXplQ29udHJhY3REZWNvZGVkO1xuICB0cnkge1xuICAgIHVuZnJlZXplQ29udHJhY3QgPSBwcm90b2NvbC5VbmZyZWV6ZUJhbGFuY2VWMkNvbnRyYWN0LmRlY29kZShCdWZmZXIuZnJvbShiYXNlNjQsICdiYXNlNjQnKSkudG9KU09OKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignVGhlcmUgd2FzIGFuIGVycm9yIGRlY29kaW5nIHRoZSB1bmZyZWV6ZSBjb250cmFjdCBpbiB0aGUgdHJhbnNhY3Rpb24uJyk7XG4gIH1cblxuICBpZiAoIXVuZnJlZXplQ29udHJhY3Qub3duZXJBZGRyZXNzKSB7XG4gICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ093bmVyIGFkZHJlc3MgZG9lcyBub3QgZXhpc3QgaW4gdGhpcyB1bmZyZWV6ZSBjb250cmFjdC4nKTtcbiAgfVxuXG4gIGlmICh1bmZyZWV6ZUNvbnRyYWN0LnJlc291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignUmVzb3VyY2UgdHlwZSBkb2VzIG5vdCBleGlzdCBpbiB0aGlzIHVuZnJlZXplIGNvbnRyYWN0LicpO1xuICB9XG5cbiAgaWYgKHVuZnJlZXplQ29udHJhY3QudW5mcmVlemVCYWxhbmNlID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignVW5mcmVlemUgYmFsYW5jZSBkb2VzIG5vdCBleGlzdCBpbiB0aGlzIHVuZnJlZXplIGNvbnRyYWN0LicpO1xuICB9XG5cbiAgLy8gZGVzZXJpYWxpemUgYXR0cmlidXRlc1xuICBjb25zdCBvd25lcl9hZGRyZXNzID0gZ2V0QmFzZTU4QWRkcmVzc0Zyb21CeXRlQXJyYXkoXG4gICAgZ2V0Qnl0ZUFycmF5RnJvbUhleEFkZHJlc3MoQnVmZmVyLmZyb20odW5mcmVlemVDb250cmFjdC5vd25lckFkZHJlc3MsICdiYXNlNjQnKS50b1N0cmluZygnaGV4JykpXG4gICk7XG5cbiAgLy8gQ29udmVydCBSZXNvdXJjZUNvZGUgZW51bSB2YWx1ZSB0byBzdHJpbmcgcmVzb3VyY2UgbmFtZVxuICBjb25zdCByZXNvdXJjZVZhbHVlID0gdW5mcmVlemVDb250cmFjdC5yZXNvdXJjZTtcbiAgY29uc3QgcmVzb3VyY2VFbnVtID0gcmVzb3VyY2VWYWx1ZSA9PT0gcHJvdG9jb2wuUmVzb3VyY2VDb2RlLkJBTkRXSURUSCA/IFRyb25SZXNvdXJjZS5CQU5EV0lEVEggOiBUcm9uUmVzb3VyY2UuRU5FUkdZO1xuXG4gIHJldHVybiBbXG4gICAge1xuICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgcmVzb3VyY2U6IHJlc291cmNlRW51bSxcbiAgICAgICAgICB1bmZyZWV6ZV9iYWxhbmNlOiBOdW1iZXIodW5mcmVlemVDb250cmFjdC51bmZyZWV6ZUJhbGFuY2UpLFxuICAgICAgICAgIG93bmVyX2FkZHJlc3MsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIF07XG59XG5cbi8qKlxuICogRGVzZXJpYWxpemUgdGhlIHNlZ21lbnQgb2YgdGhlIHR4SGV4IGNvcnJlc3BvbmRpbmcgd2l0aCB3aXRoZHJhdyBiYWxhbmNlIGNvbnRyYWN0XG4gKiBEZWNvZGVkIGNvbnRyYWN0IGlzIHRoZSBzYW1lIGFzIHdpdGhkcmF3IGV4cGlyZSB1bmZyZWV6ZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlNjQgLSBUaGUgYmFzZTY0IGVuY29kZWQgY29udHJhY3QgZGF0YVxuICogQHJldHVybnMge1dpdGhkcmF3RXhwaXJlVW5mcmVlemVDb250cmFjdFBhcmFtZXRlcltdfSAtIEFycmF5IGNvbnRhaW5pbmcgdGhlIGRlY29kZWQgd2l0aGRyYXcgY29udHJhY3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVdpdGhkcmF3QmFsYW5jZUNvbnRyYWN0KGJhc2U2NDogc3RyaW5nKTogV2l0aGRyYXdFeHBpcmVVbmZyZWV6ZUNvbnRyYWN0UGFyYW1ldGVyW10ge1xuICBsZXQgd2l0aGRyYXdDb250cmFjdDogV2l0aGRyYXdDb250cmFjdERlY29kZWQ7XG4gIHRyeSB7XG4gICAgd2l0aGRyYXdDb250cmFjdCA9IHByb3RvY29sLldpdGhkcmF3QmFsYW5jZUNvbnRyYWN0LmRlY29kZShCdWZmZXIuZnJvbShiYXNlNjQsICdiYXNlNjQnKSkudG9KU09OKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignVGhlcmUgd2FzIGFuIGVycm9yIGRlY29kaW5nIHRoZSB3aXRoZHJhdyBjb250cmFjdCBpbiB0aGUgdHJhbnNhY3Rpb24uJyk7XG4gIH1cblxuICBpZiAoIXdpdGhkcmF3Q29udHJhY3Qub3duZXJBZGRyZXNzKSB7XG4gICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ093bmVyIGFkZHJlc3MgZG9lcyBub3QgZXhpc3QgaW4gdGhpcyB3aXRoZHJhdyBjb250cmFjdC4nKTtcbiAgfVxuXG4gIC8vIGRlc2VyaWFsaXplIGF0dHJpYnV0ZXNcbiAgY29uc3Qgb3duZXJfYWRkcmVzcyA9IGdldEJhc2U1OEFkZHJlc3NGcm9tQnl0ZUFycmF5KFxuICAgIGdldEJ5dGVBcnJheUZyb21IZXhBZGRyZXNzKEJ1ZmZlci5mcm9tKHdpdGhkcmF3Q29udHJhY3Qub3duZXJBZGRyZXNzLCAnYmFzZTY0JykudG9TdHJpbmcoJ2hleCcpKVxuICApO1xuXG4gIHJldHVybiBbXG4gICAge1xuICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgb3duZXJfYWRkcmVzcyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgXTtcbn1cblxuLyoqXG4gKiBEZXNlcmlhbGl6ZSB0aGUgc2VnbWVudCBvZiB0aGUgdHhIZXggY29ycmVzcG9uZGluZyB3aXRoIHdpdGhkcmF3IGV4cGlyZSB1bmZyZWV6ZSBjb250cmFjdFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlNjQgLSBUaGUgYmFzZTY0IGVuY29kZWQgY29udHJhY3QgZGF0YVxuICogQHJldHVybnMge1dpdGhkcmF3RXhwaXJlVW5mcmVlemVDb250cmFjdFBhcmFtZXRlcltdfSAtIEFycmF5IGNvbnRhaW5pbmcgdGhlIGRlY29kZWQgd2l0aGRyYXcgY29udHJhY3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVdpdGhkcmF3RXhwaXJlVW5mcmVlemVDb250cmFjdChiYXNlNjQ6IHN0cmluZyk6IFdpdGhkcmF3RXhwaXJlVW5mcmVlemVDb250cmFjdFBhcmFtZXRlcltdIHtcbiAgbGV0IHdpdGhkcmF3Q29udHJhY3Q6IFdpdGhkcmF3Q29udHJhY3REZWNvZGVkO1xuICB0cnkge1xuICAgIHdpdGhkcmF3Q29udHJhY3QgPSBwcm90b2NvbC5XaXRoZHJhd0JhbGFuY2VDb250cmFjdC5kZWNvZGUoQnVmZmVyLmZyb20oYmFzZTY0LCAnYmFzZTY0JykpLnRvSlNPTigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ1RoZXJlIHdhcyBhbiBlcnJvciBkZWNvZGluZyB0aGUgd2l0aGRyYXcgY29udHJhY3QgaW4gdGhlIHRyYW5zYWN0aW9uLicpO1xuICB9XG5cbiAgaWYgKCF3aXRoZHJhd0NvbnRyYWN0Lm93bmVyQWRkcmVzcykge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdPd25lciBhZGRyZXNzIGRvZXMgbm90IGV4aXN0IGluIHRoaXMgd2l0aGRyYXcgY29udHJhY3QuJyk7XG4gIH1cblxuICAvLyBkZXNlcmlhbGl6ZSBhdHRyaWJ1dGVzXG4gIGNvbnN0IG93bmVyX2FkZHJlc3MgPSBnZXRCYXNlNThBZGRyZXNzRnJvbUJ5dGVBcnJheShcbiAgICBnZXRCeXRlQXJyYXlGcm9tSGV4QWRkcmVzcyhCdWZmZXIuZnJvbSh3aXRoZHJhd0NvbnRyYWN0Lm93bmVyQWRkcmVzcywgJ2Jhc2U2NCcpLnRvU3RyaW5nKCdoZXgnKSlcbiAgKTtcblxuICByZXR1cm4gW1xuICAgIHtcbiAgICAgIHBhcmFtZXRlcjoge1xuICAgICAgICB2YWx1ZToge1xuICAgICAgICAgIG93bmVyX2FkZHJlc3MsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIF07XG59XG5cbi8qKlxuICogRGVzZXJpYWxpemUgdGhlIHNlZ21lbnQgb2YgdGhlIHR4SGV4IGNvcnJlc3BvbmRpbmcgd2l0aCBkZWxlZ2F0ZSByZXNvdXJjZSBjb250cmFjdFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlNjQgLSBUaGUgYmFzZTY0IGVuY29kZWQgY29udHJhY3QgZGF0YVxuICogQHJldHVybnMge1Jlc291cmNlTWFuYWdlbWVudENvbnRyYWN0UGFyYW1ldGVyW119IC0gQXJyYXkgY29udGFpbmluZyB0aGUgZGVjb2RlZCBkZWxlZ2F0ZSByZXNvdXJjZSBjb250cmFjdFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlRGVsZWdhdGVSZXNvdXJjZUNvbnRyYWN0KGJhc2U2NDogc3RyaW5nKTogUmVzb3VyY2VNYW5hZ2VtZW50Q29udHJhY3RQYXJhbWV0ZXJbXSB7XG4gIGxldCBkZWxlZ2F0ZVJlc291cmNlQ29udHJhY3Q6IFJlc291cmNlTWFuYWdlbWVudENvbnRyYWN0RGVjb2RlZDtcbiAgdHJ5IHtcbiAgICBkZWxlZ2F0ZVJlc291cmNlQ29udHJhY3QgPSBwcm90b2NvbC5EZWxlZ2F0ZVJlc291cmNlQ29udHJhY3QuZGVjb2RlKEJ1ZmZlci5mcm9tKGJhc2U2NCwgJ2Jhc2U2NCcpKS50b0pTT04oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdUaGVyZSB3YXMgYW4gZXJyb3IgZGVjb2RpbmcgdGhlIGRlbGVnYXRlIHJlc291cmNlIGNvbnRyYWN0IGluIHRoZSB0cmFuc2FjdGlvbi4nKTtcbiAgfVxuXG4gIGlmICghZGVsZWdhdGVSZXNvdXJjZUNvbnRyYWN0Lm93bmVyQWRkcmVzcykge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdPd25lciBhZGRyZXNzIGRvZXMgbm90IGV4aXN0IGluIHRoaXMgZGVsZWdhdGUgcmVzb3VyY2UgY29udHJhY3QuJyk7XG4gIH1cblxuICBpZiAoIWRlbGVnYXRlUmVzb3VyY2VDb250cmFjdC5yZWNlaXZlckFkZHJlc3MpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignUmVjZWl2ZXIgYWRkcmVzcyBkb2VzIG5vdCBleGlzdCBpbiB0aGlzIGRlbGVnYXRlIHJlc291cmNlIGNvbnRyYWN0LicpO1xuICB9XG5cbiAgaWYgKGRlbGVnYXRlUmVzb3VyY2VDb250cmFjdC5yZXNvdXJjZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ1Jlc291cmNlIHR5cGUgZG9lcyBub3QgZXhpc3QgaW4gdGhpcyBkZWxlZ2F0ZSByZXNvdXJjZSBjb250cmFjdC4nKTtcbiAgfVxuXG4gIGlmIChkZWxlZ2F0ZVJlc291cmNlQ29udHJhY3QuYmFsYW5jZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ0JhbGFuY2UgZG9lcyBub3QgZXhpc3QgaW4gdGhpcyBkZWxlZ2F0ZSByZXNvdXJjZSBjb250cmFjdC4nKTtcbiAgfVxuXG4gIGNvbnN0IG93bmVyX2FkZHJlc3MgPSBnZXRCYXNlNThBZGRyZXNzRnJvbUJ5dGVBcnJheShcbiAgICBnZXRCeXRlQXJyYXlGcm9tSGV4QWRkcmVzcyhCdWZmZXIuZnJvbShkZWxlZ2F0ZVJlc291cmNlQ29udHJhY3Qub3duZXJBZGRyZXNzLCAnYmFzZTY0JykudG9TdHJpbmcoJ2hleCcpKVxuICApO1xuXG4gIGNvbnN0IHJlY2VpdmVyX2FkZHJlc3MgPSBnZXRCYXNlNThBZGRyZXNzRnJvbUJ5dGVBcnJheShcbiAgICBnZXRCeXRlQXJyYXlGcm9tSGV4QWRkcmVzcyhCdWZmZXIuZnJvbShkZWxlZ2F0ZVJlc291cmNlQ29udHJhY3QucmVjZWl2ZXJBZGRyZXNzLCAnYmFzZTY0JykudG9TdHJpbmcoJ2hleCcpKVxuICApO1xuXG4gIGNvbnN0IHJlc291cmNlVmFsdWUgPSAhZGVsZWdhdGVSZXNvdXJjZUNvbnRyYWN0LnJlc291cmNlID8gVHJvblJlc291cmNlLkJBTkRXSURUSCA6IFRyb25SZXNvdXJjZS5FTkVSR1k7XG5cbiAgcmV0dXJuIFtcbiAgICB7XG4gICAgICBwYXJhbWV0ZXI6IHtcbiAgICAgICAgdmFsdWU6IHtcbiAgICAgICAgICByZXNvdXJjZTogcmVzb3VyY2VWYWx1ZSxcbiAgICAgICAgICBiYWxhbmNlOiBOdW1iZXIoZGVsZWdhdGVSZXNvdXJjZUNvbnRyYWN0LmJhbGFuY2UpLFxuICAgICAgICAgIG93bmVyX2FkZHJlc3MsXG4gICAgICAgICAgcmVjZWl2ZXJfYWRkcmVzcyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgXTtcbn1cblxuLyoqXG4gKiBEZXNlcmlhbGl6ZSB0aGUgc2VnbWVudCBvZiB0aGUgdHhIZXggY29ycmVzcG9uZGluZyB3aXRoIHVuZGVsZWdhdGUgcmVzb3VyY2UgY29udHJhY3RcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gYmFzZTY0IC0gVGhlIGJhc2U2NCBlbmNvZGVkIGNvbnRyYWN0IGRhdGFcbiAqIEByZXR1cm5zIHtSZXNvdXJjZU1hbmFnZW1lbnRDb250cmFjdFBhcmFtZXRlcltdfSAtIEFycmF5IGNvbnRhaW5pbmcgdGhlIGRlY29kZWQgdW5kZWxlZ2F0ZSByZXNvdXJjZSBjb250cmFjdFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlVW5EZWxlZ2F0ZVJlc291cmNlQ29udHJhY3QoYmFzZTY0OiBzdHJpbmcpOiBSZXNvdXJjZU1hbmFnZW1lbnRDb250cmFjdFBhcmFtZXRlcltdIHtcbiAgbGV0IHVuZGVsZWdhdGVSZXNvdXJjZUNvbnRyYWN0OiBSZXNvdXJjZU1hbmFnZW1lbnRDb250cmFjdERlY29kZWQ7XG4gIHRyeSB7XG4gICAgdW5kZWxlZ2F0ZVJlc291cmNlQ29udHJhY3QgPSBwcm90b2NvbC5VbkRlbGVnYXRlUmVzb3VyY2VDb250cmFjdC5kZWNvZGUoQnVmZmVyLmZyb20oYmFzZTY0LCAnYmFzZTY0JykpLnRvSlNPTigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ1RoZXJlIHdhcyBhbiBlcnJvciBkZWNvZGluZyB0aGUgZGVsZWdhdGUgcmVzb3VyY2UgY29udHJhY3QgaW4gdGhlIHRyYW5zYWN0aW9uLicpO1xuICB9XG5cbiAgaWYgKCF1bmRlbGVnYXRlUmVzb3VyY2VDb250cmFjdC5vd25lckFkZHJlc3MpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignT3duZXIgYWRkcmVzcyBkb2VzIG5vdCBleGlzdCBpbiB0aGlzIGRlbGVnYXRlIHJlc291cmNlIGNvbnRyYWN0LicpO1xuICB9XG5cbiAgaWYgKCF1bmRlbGVnYXRlUmVzb3VyY2VDb250cmFjdC5yZWNlaXZlckFkZHJlc3MpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignUmVjZWl2ZXIgYWRkcmVzcyBkb2VzIG5vdCBleGlzdCBpbiB0aGlzIGRlbGVnYXRlIHJlc291cmNlIGNvbnRyYWN0LicpO1xuICB9XG5cbiAgaWYgKHVuZGVsZWdhdGVSZXNvdXJjZUNvbnRyYWN0LnJlc291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignUmVzb3VyY2UgdHlwZSBkb2VzIG5vdCBleGlzdCBpbiB0aGlzIGRlbGVnYXRlIHJlc291cmNlIGNvbnRyYWN0LicpO1xuICB9XG5cbiAgaWYgKHVuZGVsZWdhdGVSZXNvdXJjZUNvbnRyYWN0LmJhbGFuY2UgPT09IHVuZGVmaW5lZCkge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdCYWxhbmNlIGRvZXMgbm90IGV4aXN0IGluIHRoaXMgZGVsZWdhdGUgcmVzb3VyY2UgY29udHJhY3QuJyk7XG4gIH1cblxuICBjb25zdCBvd25lcl9hZGRyZXNzID0gZ2V0QmFzZTU4QWRkcmVzc0Zyb21CeXRlQXJyYXkoXG4gICAgZ2V0Qnl0ZUFycmF5RnJvbUhleEFkZHJlc3MoQnVmZmVyLmZyb20odW5kZWxlZ2F0ZVJlc291cmNlQ29udHJhY3Qub3duZXJBZGRyZXNzLCAnYmFzZTY0JykudG9TdHJpbmcoJ2hleCcpKVxuICApO1xuXG4gIGNvbnN0IHJlY2VpdmVyX2FkZHJlc3MgPSBnZXRCYXNlNThBZGRyZXNzRnJvbUJ5dGVBcnJheShcbiAgICBnZXRCeXRlQXJyYXlGcm9tSGV4QWRkcmVzcyhCdWZmZXIuZnJvbSh1bmRlbGVnYXRlUmVzb3VyY2VDb250cmFjdC5yZWNlaXZlckFkZHJlc3MsICdiYXNlNjQnKS50b1N0cmluZygnaGV4JykpXG4gICk7XG5cbiAgY29uc3QgcmVzb3VyY2VWYWx1ZSA9ICF1bmRlbGVnYXRlUmVzb3VyY2VDb250cmFjdC5yZXNvdXJjZSA/IFRyb25SZXNvdXJjZS5CQU5EV0lEVEggOiBUcm9uUmVzb3VyY2UuRU5FUkdZO1xuXG4gIHJldHVybiBbXG4gICAge1xuICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgcmVzb3VyY2U6IHJlc291cmNlVmFsdWUsXG4gICAgICAgICAgYmFsYW5jZTogTnVtYmVyKHVuZGVsZWdhdGVSZXNvdXJjZUNvbnRyYWN0LmJhbGFuY2UpLFxuICAgICAgICAgIG93bmVyX2FkZHJlc3MsXG4gICAgICAgICAgcmVjZWl2ZXJfYWRkcmVzcyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgXTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gcmF3XG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVBlcm1pc3Npb24ocmF3OiB7IHBlcm1pc3Npb25OYW1lOiBzdHJpbmc7IHRocmVzaG9sZDogbnVtYmVyIH0pOiBQZXJtaXNzaW9uIHtcbiAgbGV0IHBlcm1pc3Npb25UeXBlOiBQZXJtaXNzaW9uVHlwZTtcbiAgY29uc3QgcGVybWlzc2lvbiA9IHJhdy5wZXJtaXNzaW9uTmFtZS50b0xvd2VyQ2FzZSgpLnRyaW0oKTtcbiAgaWYgKHBlcm1pc3Npb24gPT09ICdvd25lcicpIHtcbiAgICBwZXJtaXNzaW9uVHlwZSA9IFBlcm1pc3Npb25UeXBlLk93bmVyO1xuICB9IGVsc2UgaWYgKHBlcm1pc3Npb24gPT09ICd3aXRuZXNzJykge1xuICAgIHBlcm1pc3Npb25UeXBlID0gUGVybWlzc2lvblR5cGUuV2l0bmVzcztcbiAgfSBlbHNlIGlmIChwZXJtaXNzaW9uLnN1YnN0cigwLCA2KSA9PT0gJ2FjdGl2ZScpIHtcbiAgICBwZXJtaXNzaW9uVHlwZSA9IFBlcm1pc3Npb25UeXBlLkFjdGl2ZTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignUGVybWlzc2lvbiB0eXBlIG5vdCBwYXJzZWFibGUuJyk7XG4gIH1cbiAgcmV0dXJuIHsgdHlwZTogcGVybWlzc2lvblR5cGUsIHRocmVzaG9sZDogcmF3LnRocmVzaG9sZCB9O1xufVxuXG4vKipcbiAqIEBwYXJhbSByYXdUcmFuc2FjdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZFR4SnNvblN0cmluZyhyYXdUcmFuc2FjdGlvbjogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IHRyYW5zYWN0aW9uID0gSlNPTi5wYXJzZShyYXdUcmFuc2FjdGlvbik7XG4gIHJldHVybiB0cmFuc2FjdGlvbi5oYXNPd25Qcm9wZXJ0eSgndHhJRCcpO1xufVxuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciB0aGUgcHJvdmlkZWQgcmF3IHRyYW5zYWN0aW9uIGFjY29tbW9kYXRlcyB0byBiaXRnbydzIHByZWZlcnJlZCBmb3JtYXRcbiAqXG4gKiBAcGFyYW0ge2FueX0gcmF3VHJhbnNhY3Rpb24gLSBUaGUgcmF3IHRyYW5zYWN0aW9uIHRvIGJlIGNoZWNrZWRcbiAqIEByZXR1cm5zIHtib29sZWFufSB0aGUgdmFsaWRhdGlvbiByZXN1bHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRSYXdUcmFuc2FjdGlvbkZvcm1hdChyYXdUcmFuc2FjdGlvbjogYW55KTogYm9vbGVhbiB7XG4gIGlmICh0eXBlb2YgcmF3VHJhbnNhY3Rpb24gPT09ICdzdHJpbmcnICYmIChpc1ZhbGlkSGV4KHJhd1RyYW5zYWN0aW9uKSB8fCBpc1ZhbGlkVHhKc29uU3RyaW5nKHJhd1RyYW5zYWN0aW9uKSkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogUmV0dXJucyBhbiBoZXggc3RyaW5nIG9mIHRoZSBnaXZlbiBidWZmZXJcbiAqXG4gKiBAcGFyYW0ge0J1ZmZlciB8IFVpbnQ4QXJyYXl9IGJ1ZmZlciAtIHRoZSBidWZmZXIgdG8gYmUgY29udmVydGVkIHRvIGhleFxuICogQHJldHVybnMge3N0cmluZ30gLSB0aGUgaGV4IHZhbHVlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b0hleChidWZmZXI6IEJ1ZmZlciB8IFVpbnQ4QXJyYXkpOiBzdHJpbmcge1xuICByZXR1cm4gaGV4LmVuY29kZShidWZmZXIsIHRydWUpO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBLZWNjYWstMjU2IGVuY29kZWQgc3RyaW5nIG9mIHRoZSBwYXJhbWV0ZXJzXG4gKlxuICogQHBhcmFtIHR5cGVzIC0gc3RyaW5ncyBkZXNjcmliaW5nIHRoZSB0eXBlcyBvZiB0aGUgdmFsdWVzXG4gKiBAcGFyYW0gdmFsdWVzIC0gdmFsdWUgdG8gZW5jb2RlXG4gKiBAcGFyYW0gbWV0aG9kSWQgLSB0aGUgZmlyc3QgNCBieXRlcyBvZiB0aGUgZnVuY3Rpb24gc2VsZWN0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZURhdGFQYXJhbXModHlwZXM6IHN0cmluZ1tdLCB2YWx1ZXM6IGFueVtdLCBtZXRob2RJZD86IHN0cmluZyk6IHN0cmluZyB7XG4gIHR5cGVzLmZvckVhY2goKHR5cGUsIGluZGV4KSA9PiB7XG4gICAgaWYgKHR5cGUgPT0gJ2FkZHJlc3MnKSB7XG4gICAgICB2YWx1ZXNbaW5kZXhdID0gdmFsdWVzW2luZGV4XS5yZXBsYWNlKEFERFJFU1NfUFJFRklYX1JFR0VYLCAnMHgnKTtcbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IGFiaUNvZGVyID0gbmV3IEFiaUNvZGVyKCk7XG4gIGxldCBkYXRhO1xuICB0cnkge1xuICAgIGRhdGEgPSBhYmlDb2Rlci5lbmNvZGUodHlwZXMsIHZhbHVlcyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcihgVGhlcmUgd2FzIGFuIGVycm9yIGVuY29kaW5nIHRoZSBkYXRhIHBhcmFtcy4gRXJyb3IgPSAke0pTT04uc3RyaW5naWZ5KGUpfWApO1xuICB9XG4gIGlmIChtZXRob2RJZCkge1xuICAgIHJldHVybiBoZXhDb25jYXQoW21ldGhvZElkLCBkYXRhXSkucmVwbGFjZSgvXigweCkvLCAnJyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGRhdGEucmVwbGFjZSgvXigweCkvLCAnJyk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBkZWNvZGVkIHZhbHVlcyBhY2NvcmRpbmcgdG8gdGhlIGFycmF5IG9mIHR5cGVzXG4gKlxuICogQHBhcmFtIHR5cGVzIC0gc3RyaW5ncyBkZXNjcmliaW5nIHRoZSB0eXBlcyBvZiB0aGUgdmFsdWVzXG4gKiBAcGFyYW0gZGF0YSAtIGVuY29kZWQgc3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVEYXRhUGFyYW1zKHR5cGVzOiBzdHJpbmdbXSwgZGF0YTogc3RyaW5nKTogYW55W10ge1xuICBjb25zdCBhYmlDb2RlciA9IG5ldyBBYmlDb2RlcigpO1xuICBkYXRhID0gJzB4JyArIGRhdGEuc3Vic3RyaW5nKDgpO1xuICByZXR1cm4gYWJpQ29kZXIuZGVjb2RlKHR5cGVzLCBkYXRhKS5yZWR1Y2UoKG9iaiwgYXJnLCBpbmRleCkgPT4ge1xuICAgIGlmICh0eXBlc1tpbmRleF0gPT0gJ2FkZHJlc3MnKSBhcmcgPSBBRERSRVNTX1BSRUZJWCArIGFyZy5zdWJzdHIoMikudG9Mb3dlckNhc2UoKTtcbiAgICBvYmoucHVzaChhcmcpO1xuICAgIHJldHVybiBvYmo7XG4gIH0sIFtdKTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZSByYXdfZGF0YV9oZXggZm9yIGEgVFJPTiB0cmFuc2FjdGlvblxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSByYXdEYXRhIC0gVGhlIHRyYW5zYWN0aW9uIHJhdyBkYXRhIG9iamVjdCBjb250YWluaW5nOlxuICogQHBhcmFtIHtBcnJheX0gcmF3RGF0YS5jb250cmFjdCAtIEFycmF5IG9mIGNvbnRyYWN0IG9iamVjdHNcbiAqIEBwYXJhbSB7c3RyaW5nfSByYXdEYXRhLnJlZkJsb2NrQnl0ZXMgLSBSZWZlcmVuY2UgYmxvY2sgYnl0ZXNcbiAqIEBwYXJhbSB7c3RyaW5nfSByYXdEYXRhLnJlZkJsb2NrSGFzaCAtIFJlZmVyZW5jZSBibG9jayBoYXNoXG4gKiBAcGFyYW0ge251bWJlcn0gcmF3RGF0YS5leHBpcmF0aW9uIC0gVHJhbnNhY3Rpb24gZXhwaXJhdGlvbiB0aW1lc3RhbXBcbiAqIEBwYXJhbSB7bnVtYmVyfSByYXdEYXRhLnRpbWVzdGFtcCAtIFRyYW5zYWN0aW9uIGNyZWF0aW9uIHRpbWVzdGFtcFxuICogQHBhcmFtIHtudW1iZXJ9IFtyYXdEYXRhLmZlZUxpbWl0XSAtIE9wdGlvbmFsIGZlZSBsaW1pdCBmb3Igc21hcnQgY29udHJhY3RzXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgaGV4IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgZW5jb2RlZCB0cmFuc2FjdGlvbiBkYXRhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZVJhd0RhdGFIZXgoXG4gIHJhd0RhdGE6IHtcbiAgICBjb250cmFjdD86IHByb3RvY29sLlRyYW5zYWN0aW9uLkNvbnRyYWN0W107XG4gICAgcmVmQmxvY2tCeXRlcz86IHN0cmluZztcbiAgICByZWZCbG9ja0hhc2g/OiBzdHJpbmc7XG4gICAgZXhwaXJhdGlvbj86IG51bWJlcjtcbiAgICB0aW1lc3RhbXA/OiBudW1iZXI7XG4gICAgZmVlTGltaXQ/OiBudW1iZXI7XG4gIH0gPSB7fVxuKTogc3RyaW5nIHtcbiAgdHJ5IHtcbiAgICAvLyBQcm9jZXNzIGNvbnRyYWN0cyB0byBlbnN1cmUgcHJvcGVyIHByb3RvYnVmIGVuY29kaW5nXG4gICAgbGV0IHByb2Nlc3NlZENvbnRyYWN0cyA9IHJhd0RhdGEuY29udHJhY3Q7XG4gICAgaWYgKHJhd0RhdGEuY29udHJhY3QgJiYgcmF3RGF0YS5jb250cmFjdC5sZW5ndGggPiAwKSB7XG4gICAgICBwcm9jZXNzZWRDb250cmFjdHMgPSByYXdEYXRhLmNvbnRyYWN0Lm1hcCgoY29udHJhY3QpID0+IHtcbiAgICAgICAgLy8gSGFuZGxlIFRyYW5zZmVyQ29udHJhY3Qgc3BlY2lmaWNhbGx5XG4gICAgICAgIGlmIChjb250cmFjdC5wYXJhbWV0ZXI/LnR5cGVfdXJsID09PSAndHlwZS5nb29nbGVhcGlzLmNvbS9wcm90b2NvbC5UcmFuc2ZlckNvbnRyYWN0Jykge1xuICAgICAgICAgIGNvbnN0IGNvbnRyYWN0VmFsdWUgPSBjb250cmFjdC5wYXJhbWV0ZXIudmFsdWUgYXMgYW55O1xuXG4gICAgICAgICAgLy8gQ3JlYXRlIHRoZSBwcm90b2J1ZiBjb250cmFjdCBvYmplY3RcbiAgICAgICAgICBjb25zdCB0cmFuc2ZlckNvbnRyYWN0OiBhbnkgPSB7fTtcblxuICAgICAgICAgIC8vIEhhbmRsZSBvd25lcl9hZGRyZXNzIChyZXF1aXJlZCBmaWVsZClcbiAgICAgICAgICBpZiAoY29udHJhY3RWYWx1ZS5vd25lcl9hZGRyZXNzKSB7XG4gICAgICAgICAgICB0cmFuc2ZlckNvbnRyYWN0Lm93bmVyQWRkcmVzcyA9IEJ1ZmZlci5mcm9tKGNvbnRyYWN0VmFsdWUub3duZXJfYWRkcmVzcywgJ2hleCcpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIEhhbmRsZSB0b19hZGRyZXNzIChyZXF1aXJlZCBmaWVsZClcbiAgICAgICAgICBpZiAoY29udHJhY3RWYWx1ZS50b19hZGRyZXNzKSB7XG4gICAgICAgICAgICB0cmFuc2ZlckNvbnRyYWN0LnRvQWRkcmVzcyA9IEJ1ZmZlci5mcm9tKGNvbnRyYWN0VmFsdWUudG9fYWRkcmVzcywgJ2hleCcpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIEhhbmRsZSBhbW91bnQgKHJlcXVpcmVkIGZpZWxkKVxuICAgICAgICAgIGlmIChjb250cmFjdFZhbHVlLmFtb3VudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0cmFuc2ZlckNvbnRyYWN0LmFtb3VudCA9IGNvbnRyYWN0VmFsdWUuYW1vdW50O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIEVuY29kZSB0aGUgY29udHJhY3QgdXNpbmcgcHJvdG9idWZcbiAgICAgICAgICBjb25zdCBlbmNvZGVkQ29udHJhY3QgPSBwcm90b2NvbC5UcmFuc2ZlckNvbnRyYWN0LmVuY29kZSh0cmFuc2ZlckNvbnRyYWN0KS5maW5pc2goKTtcbiAgICAgICAgICBjb25zdCBiYXNlNjRWYWx1ZSA9IEJ1ZmZlci5mcm9tKGVuY29kZWRDb250cmFjdCkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLmNvbnRyYWN0LFxuICAgICAgICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgICAgICAgIC4uLmNvbnRyYWN0LnBhcmFtZXRlcixcbiAgICAgICAgICAgICAgdmFsdWU6IGJhc2U2NFZhbHVlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9IGFzIGFueTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjb250cmFjdDtcbiAgICAgIH0pIGFzIHByb3RvY29sLlRyYW5zYWN0aW9uLkNvbnRyYWN0W107XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIHJhdyB0cmFuc2FjdGlvbiBvYmplY3QgbWF0Y2hpbmcgcHJvdG9idWYgc2NoZW1hXG4gICAgY29uc3QgcmF3VHg6IHByb3RvY29sLlRyYW5zYWN0aW9uLklyYXcgPSB7XG4gICAgICBjb250cmFjdDogcHJvY2Vzc2VkQ29udHJhY3RzLFxuICAgICAgcmVmQmxvY2tCeXRlczogcmF3RGF0YS5yZWZCbG9ja0J5dGVzID8gQnVmZmVyLmZyb20ocmF3RGF0YS5yZWZCbG9ja0J5dGVzLCAnaGV4JykgOiB1bmRlZmluZWQsXG4gICAgICByZWZCbG9ja0hhc2g6IHJhd0RhdGEucmVmQmxvY2tIYXNoID8gQnVmZmVyLmZyb20ocmF3RGF0YS5yZWZCbG9ja0hhc2gsICdoZXgnKSA6IHVuZGVmaW5lZCxcbiAgICAgIGV4cGlyYXRpb246IHJhd0RhdGEuZXhwaXJhdGlvbixcbiAgICAgIHRpbWVzdGFtcDogcmF3RGF0YS50aW1lc3RhbXAsXG4gICAgICBmZWVMaW1pdDogcmF3RGF0YS5mZWVMaW1pdCxcbiAgICB9O1xuXG4gICAgLy8gRW5jb2RlIHVzaW5nIHByb3RvYnVmIGFuZCBnZXQgZmluYWwgYnl0ZXNcbiAgICBjb25zdCBlbmNvZGVkQnl0ZXMgPSBwcm90b2NvbC5UcmFuc2FjdGlvbi5yYXcuZW5jb2RlKHJhd1R4KS5maW5pc2goKTtcblxuICAgIC8vIENvbnZlcnQgdG8gaGV4IHN0cmluZ1xuICAgIHJldHVybiBCdWZmZXIuZnJvbShlbmNvZGVkQnl0ZXMpLnRvU3RyaW5nKCdoZXgnKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdGYWlsZWQgdG8gZ2VuZXJhdGUgcmF3IGRhdGEgaGV4OiAnICsgZS5tZXNzYWdlKTtcbiAgfVxufVxuIl19
|