@bitgo-beta/abstract-cosmos 0.0.0-semantic-release-managed
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/.eslintignore +5 -0
- package/.mocharc.yml +8 -0
- package/CHANGELOG.md +1056 -0
- package/LICENSE +191 -0
- package/README.md +1 -0
- package/dist/resources/MsgCompiled.d.ts +1212 -0
- package/dist/resources/MsgCompiled.js +2761 -0
- package/dist/src/cosmosCoin.d.ts +196 -0
- package/dist/src/cosmosCoin.d.ts.map +1 -0
- package/dist/src/cosmosCoin.js +718 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +21 -0
- package/dist/src/lib/ContractCallBuilder.d.ts +13 -0
- package/dist/src/lib/ContractCallBuilder.d.ts.map +1 -0
- package/dist/src/lib/ContractCallBuilder.js +61 -0
- package/dist/src/lib/StakingActivateBuilder.d.ts +13 -0
- package/dist/src/lib/StakingActivateBuilder.d.ts.map +1 -0
- package/dist/src/lib/StakingActivateBuilder.js +61 -0
- package/dist/src/lib/StakingDeactivateBuilder.d.ts +13 -0
- package/dist/src/lib/StakingDeactivateBuilder.d.ts.map +1 -0
- package/dist/src/lib/StakingDeactivateBuilder.js +61 -0
- package/dist/src/lib/StakingRedelegateBuilder.d.ts +13 -0
- package/dist/src/lib/StakingRedelegateBuilder.d.ts.map +1 -0
- package/dist/src/lib/StakingRedelegateBuilder.js +61 -0
- package/dist/src/lib/StakingWithdrawRewardsBuilder.d.ts +13 -0
- package/dist/src/lib/StakingWithdrawRewardsBuilder.d.ts.map +1 -0
- package/dist/src/lib/StakingWithdrawRewardsBuilder.js +61 -0
- package/dist/src/lib/constants.d.ts +11 -0
- package/dist/src/lib/constants.d.ts.map +1 -0
- package/dist/src/lib/constants.js +14 -0
- package/dist/src/lib/iface.d.ts +109 -0
- package/dist/src/lib/iface.d.ts.map +1 -0
- package/dist/src/lib/iface.js +20 -0
- package/dist/src/lib/index.d.ts +14 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +63 -0
- package/dist/src/lib/keyPair.d.ts +18 -0
- package/dist/src/lib/keyPair.d.ts.map +1 -0
- package/dist/src/lib/keyPair.js +51 -0
- package/dist/src/lib/transaction.d.ts +64 -0
- package/dist/src/lib/transaction.d.ts.map +1 -0
- package/dist/src/lib/transaction.js +333 -0
- package/dist/src/lib/transactionBuilder.d.ts +86 -0
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
- package/dist/src/lib/transactionBuilder.js +181 -0
- package/dist/src/lib/transferBuilder.d.ts +13 -0
- package/dist/src/lib/transferBuilder.d.ts.map +1 -0
- package/dist/src/lib/transferBuilder.js +61 -0
- package/dist/src/lib/utils.d.ts +351 -0
- package/dist/src/lib/utils.d.ts.map +1 -0
- package/dist/src/lib/utils.js +856 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +60 -0
- package/resources/MsgCompiled.d.ts +1212 -0
- package/resources/MsgCompiled.js +2761 -0
|
@@ -0,0 +1,856 @@
|
|
|
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.CosmosUtils = void 0;
|
|
40
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
41
|
+
const amino_1 = require("@cosmjs/amino");
|
|
42
|
+
const encoding_1 = require("@cosmjs/encoding");
|
|
43
|
+
const proto_signing_1 = require("@cosmjs/proto-signing");
|
|
44
|
+
const stargate_1 = require("@cosmjs/stargate");
|
|
45
|
+
const statics_1 = require("@bitgo-beta/statics");
|
|
46
|
+
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
47
|
+
const tx_1 = require("cosmjs-types/cosmos/tx/v1beta1/tx");
|
|
48
|
+
const tx_2 = require("cosmjs-types/cosmwasm/wasm/v1/tx");
|
|
49
|
+
const crypto_1 = require("crypto");
|
|
50
|
+
const constants = __importStar(require("./constants"));
|
|
51
|
+
const keyPair_1 = require("./keyPair");
|
|
52
|
+
const { MsgSend } = require('../../resources/MsgCompiled').types;
|
|
53
|
+
class CosmosUtils {
|
|
54
|
+
constructor() {
|
|
55
|
+
this.registry = new proto_signing_1.Registry([...stargate_1.defaultRegistryTypes]);
|
|
56
|
+
this.registry.register(constants.executeContractMsgTypeUrl, tx_2.MsgExecuteContract);
|
|
57
|
+
this.registry.register('/types.MsgSend', MsgSend);
|
|
58
|
+
}
|
|
59
|
+
/** @inheritdoc */
|
|
60
|
+
isValidBlockId(hash) {
|
|
61
|
+
return this.validateBlake2b(hash);
|
|
62
|
+
}
|
|
63
|
+
/** @inheritdoc */
|
|
64
|
+
isValidPrivateKey(key) {
|
|
65
|
+
try {
|
|
66
|
+
new keyPair_1.CosmosKeyPair({ prv: key });
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** @inheritdoc */
|
|
74
|
+
isValidPublicKey(key) {
|
|
75
|
+
try {
|
|
76
|
+
new keyPair_1.CosmosKeyPair({ pub: key });
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** @inheritdoc */
|
|
84
|
+
isValidSignature(signature) {
|
|
85
|
+
throw new sdk_core_1.NotImplementedError('isValidSignature not implemented');
|
|
86
|
+
}
|
|
87
|
+
/** @inheritdoc */
|
|
88
|
+
isValidTransactionId(txId) {
|
|
89
|
+
return this.validateBlake2b(txId);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Checks if transaction hash is in valid black2b format
|
|
93
|
+
*/
|
|
94
|
+
validateBlake2b(hash) {
|
|
95
|
+
if (hash?.length !== 64) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
return hash.match(/^[a-zA-Z0-9]+$/) !== null;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Validates whether amounts are in range
|
|
102
|
+
*
|
|
103
|
+
* @param {number[]} amounts - the amounts to validate
|
|
104
|
+
* @returns {boolean} - the validation result
|
|
105
|
+
*/
|
|
106
|
+
isValidAmounts(amounts) {
|
|
107
|
+
for (const amount of amounts) {
|
|
108
|
+
if (!this.isValidAmount(amount)) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Validates whether amount is in range
|
|
116
|
+
* @param {number} amount
|
|
117
|
+
* @returns {boolean} the validation result
|
|
118
|
+
*/
|
|
119
|
+
isValidAmount(amount) {
|
|
120
|
+
const bigNumberAmount = new bignumber_js_1.default(amount);
|
|
121
|
+
if (!bigNumberAmount.isInteger() || bigNumberAmount.isLessThanOrEqualTo(0)) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Decodes raw tx data into messages, signing info, and fee data
|
|
128
|
+
* @param {string} txHex - raw base64 tx
|
|
129
|
+
* @returns {DecodedTxRaw} Decoded transaction
|
|
130
|
+
*/
|
|
131
|
+
getDecodedTxFromRawBase64(txRaw) {
|
|
132
|
+
try {
|
|
133
|
+
return (0, proto_signing_1.decodeTxRaw)((0, encoding_1.fromBase64)(txRaw));
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
throw new sdk_core_1.ParseTransactionError('Error decoding TxRaw base64 encoded string: ' + e.message);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Returns the array of messages in the body of the decoded transaction
|
|
141
|
+
* @param {DecodedTxRaw} decodedTx
|
|
142
|
+
* @returns {EncodeObject[]} messages along with type url
|
|
143
|
+
*/
|
|
144
|
+
getEncodedMessagesFromDecodedTx(decodedTx) {
|
|
145
|
+
return decodedTx.body.messages;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Checks the txn sequence is valid or not
|
|
149
|
+
* @param {number} sequence
|
|
150
|
+
*/
|
|
151
|
+
validateSequence(sequence) {
|
|
152
|
+
if (sequence < 0) {
|
|
153
|
+
throw new sdk_core_1.InvalidTransactionError('Invalid sequence: less than zero');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Pulls the sequence number from a DecodedTxRaw AuthInfo property
|
|
158
|
+
* @param {DecodedTxRaw} decodedTx
|
|
159
|
+
* @returns {number} sequence
|
|
160
|
+
*/
|
|
161
|
+
getSequenceFromDecodedTx(decodedTx) {
|
|
162
|
+
return Number(decodedTx.authInfo.signerInfos[0].sequence);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Pulls the typeUrl from the encoded message of a DecodedTxRaw
|
|
166
|
+
* @param {DecodedTxRaw} decodedTx
|
|
167
|
+
* @returns {string} cosmos proto type url
|
|
168
|
+
*/
|
|
169
|
+
getTypeUrlFromDecodedTx(decodedTx) {
|
|
170
|
+
const encodedMessage = this.getEncodedMessagesFromDecodedTx(decodedTx)[0];
|
|
171
|
+
return encodedMessage.typeUrl;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Returns the fee data from the decoded transaction
|
|
175
|
+
* @param {DecodedTxRaw} decodedTx
|
|
176
|
+
* @returns {FeeData} fee data
|
|
177
|
+
*/
|
|
178
|
+
getGasBudgetFromDecodedTx(decodedTx) {
|
|
179
|
+
return {
|
|
180
|
+
amount: decodedTx.authInfo.fee?.amount,
|
|
181
|
+
gasLimit: Number(decodedTx.authInfo.fee?.gasLimit),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Returns the publicKey from the decoded transaction
|
|
186
|
+
* @param {DecodedTxRaw} decodedTx
|
|
187
|
+
* @returns {string | undefined} publicKey in hex format if it exists, undefined otherwise
|
|
188
|
+
*/
|
|
189
|
+
getPublicKeyFromDecodedTx(decodedTx) {
|
|
190
|
+
const publicKeyUInt8Array = decodedTx.authInfo.signerInfos?.[0].publicKey?.value;
|
|
191
|
+
if (publicKeyUInt8Array) {
|
|
192
|
+
return (0, encoding_1.toHex)((0, encoding_1.fromBase64)((0, proto_signing_1.decodePubkey)(decodedTx.authInfo.signerInfos?.[0].publicKey)?.value));
|
|
193
|
+
}
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Returns the array of MessageData[] from the decoded transaction
|
|
198
|
+
* @param {DecodedTxRaw} decodedTx
|
|
199
|
+
* @returns {MessageData[]} Send transaction message data
|
|
200
|
+
*/
|
|
201
|
+
getSendMessageDataFromDecodedTx(decodedTx) {
|
|
202
|
+
return decodedTx.body.messages.map((message) => {
|
|
203
|
+
const value = this.registry.decode(message);
|
|
204
|
+
return {
|
|
205
|
+
value: {
|
|
206
|
+
fromAddress: value.fromAddress,
|
|
207
|
+
toAddress: value.toAddress,
|
|
208
|
+
amount: value.amount,
|
|
209
|
+
},
|
|
210
|
+
typeUrl: message.typeUrl,
|
|
211
|
+
};
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Returns the array of MessageData[] from the decoded transaction
|
|
216
|
+
* @param {DecodedTxRaw} decodedTx
|
|
217
|
+
* @returns {MessageData[]} Delegate of undelegate transaction message data
|
|
218
|
+
*/
|
|
219
|
+
getDelegateOrUndelegateMessageDataFromDecodedTx(decodedTx) {
|
|
220
|
+
return decodedTx.body.messages.map((message) => {
|
|
221
|
+
const value = this.registry.decode(message);
|
|
222
|
+
return {
|
|
223
|
+
value: {
|
|
224
|
+
delegatorAddress: value.delegatorAddress,
|
|
225
|
+
validatorAddress: value.validatorAddress,
|
|
226
|
+
amount: value.amount,
|
|
227
|
+
},
|
|
228
|
+
typeUrl: message.typeUrl,
|
|
229
|
+
};
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Returns the array of MessageData[] from the decoded transaction
|
|
234
|
+
* @param {DecodedTxRaw} decodedTx
|
|
235
|
+
* @returns {MessageData[]} Redelegate transaction message data
|
|
236
|
+
*/
|
|
237
|
+
getRedelegateMessageDataFromDecodedTx(decodedTx) {
|
|
238
|
+
return decodedTx.body.messages.map((message) => {
|
|
239
|
+
const value = this.registry.decode(message);
|
|
240
|
+
return {
|
|
241
|
+
value: {
|
|
242
|
+
delegatorAddress: value.delegatorAddress,
|
|
243
|
+
validatorSrcAddress: value.validatorSrcAddress,
|
|
244
|
+
validatorDstAddress: value.validatorDstAddress,
|
|
245
|
+
amount: value.amount,
|
|
246
|
+
},
|
|
247
|
+
typeUrl: message.typeUrl,
|
|
248
|
+
};
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Returns the array of MessageData[] from the decoded transaction
|
|
253
|
+
* @param {DecodedTxRaw} decodedTx
|
|
254
|
+
* @returns {MessageData[]} WithdrawDelegatorRewards transaction message data
|
|
255
|
+
*/
|
|
256
|
+
getWithdrawRewardsMessageDataFromDecodedTx(decodedTx) {
|
|
257
|
+
return decodedTx.body.messages.map((message) => {
|
|
258
|
+
const value = this.registry.decode(message);
|
|
259
|
+
return {
|
|
260
|
+
value: {
|
|
261
|
+
delegatorAddress: value.delegatorAddress,
|
|
262
|
+
validatorAddress: value.validatorAddress,
|
|
263
|
+
},
|
|
264
|
+
typeUrl: message.typeUrl,
|
|
265
|
+
};
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Returns the array of MessageData[] from the decoded transaction
|
|
270
|
+
* @param {DecodedTxRaw} decodedTx
|
|
271
|
+
* @returns {MessageData[]} Delegate of undelegate transaction message data
|
|
272
|
+
*/
|
|
273
|
+
getWithdrawDelegatorRewardsMessageDataFromDecodedTx(decodedTx) {
|
|
274
|
+
return decodedTx.body.messages.map((message) => {
|
|
275
|
+
const value = this.registry.decode(message);
|
|
276
|
+
return {
|
|
277
|
+
value: {
|
|
278
|
+
delegatorAddress: value.delegatorAddress,
|
|
279
|
+
validatorAddress: value.validatorAddress,
|
|
280
|
+
},
|
|
281
|
+
typeUrl: message.typeUrl,
|
|
282
|
+
};
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Get a cosmos chain address from its equivalent hex
|
|
287
|
+
* @param {string} prefix
|
|
288
|
+
* @param {string} addressHex
|
|
289
|
+
* @returns {string}
|
|
290
|
+
*/
|
|
291
|
+
getCosmosLikeAddressFromHex(prefix, addressHex) {
|
|
292
|
+
if (addressHex.indexOf('0x') === 0) {
|
|
293
|
+
addressHex = addressHex.slice(2);
|
|
294
|
+
}
|
|
295
|
+
return (0, encoding_1.toBech32)(prefix, (0, encoding_1.fromHex)(addressHex));
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Get a EVM chain address from its equivalent hex
|
|
299
|
+
* @param {string} prefix
|
|
300
|
+
* @param {string} addressHex
|
|
301
|
+
* @returns {string}
|
|
302
|
+
*/
|
|
303
|
+
getEvmLikeAddressFromCosmos(cosmosLikeAddress) {
|
|
304
|
+
return '0x' + (0, encoding_1.toHex)((0, encoding_1.fromBech32)(cosmosLikeAddress).data);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Returns the array of MessageData[] from the decoded transaction
|
|
308
|
+
* @param {DecodedTxRaw} decodedTx
|
|
309
|
+
* @returns {MessageData[]} Execute contract transaction message data
|
|
310
|
+
*/
|
|
311
|
+
getExecuteContractMessageDataFromDecodedTx(decodedTx) {
|
|
312
|
+
return decodedTx.body.messages.map((message) => {
|
|
313
|
+
const value = this.registry.decode(message);
|
|
314
|
+
return {
|
|
315
|
+
value: {
|
|
316
|
+
sender: value.sender,
|
|
317
|
+
contract: value.contract,
|
|
318
|
+
msg: value.msg,
|
|
319
|
+
funds: value.funds,
|
|
320
|
+
},
|
|
321
|
+
typeUrl: message.typeUrl,
|
|
322
|
+
};
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Returns the array of MessageData[] from the decoded transaction
|
|
327
|
+
* @param {DecodedTxRaw} decodedTx
|
|
328
|
+
* @returns {MessageData[]} Custom transaction message data
|
|
329
|
+
*/
|
|
330
|
+
getCustomMessageDataFromDecodedTx(decodedTx) {
|
|
331
|
+
throw new sdk_core_1.NotSupported('Custom message data not supported');
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Determines bitgo transaction type based on cosmos proto type url
|
|
335
|
+
* @param {string} typeUrl
|
|
336
|
+
* @returns {TransactionType | undefined} TransactionType if url is supported else undefined
|
|
337
|
+
*/
|
|
338
|
+
getTransactionTypeFromTypeUrl(typeUrl) {
|
|
339
|
+
switch (typeUrl) {
|
|
340
|
+
case constants.sendMsgTypeUrl:
|
|
341
|
+
return sdk_core_1.TransactionType.Send;
|
|
342
|
+
case constants.sendMsgType:
|
|
343
|
+
return sdk_core_1.TransactionType.Send;
|
|
344
|
+
case constants.delegateMsgTypeUrl:
|
|
345
|
+
return sdk_core_1.TransactionType.StakingActivate;
|
|
346
|
+
case constants.undelegateMsgTypeUrl:
|
|
347
|
+
return sdk_core_1.TransactionType.StakingDeactivate;
|
|
348
|
+
case constants.withdrawDelegatorRewardMsgTypeUrl:
|
|
349
|
+
return sdk_core_1.TransactionType.StakingWithdraw;
|
|
350
|
+
case constants.executeContractMsgTypeUrl:
|
|
351
|
+
return sdk_core_1.TransactionType.ContractCall;
|
|
352
|
+
case constants.redelegateTypeUrl:
|
|
353
|
+
return sdk_core_1.TransactionType.StakingRedelegate;
|
|
354
|
+
default:
|
|
355
|
+
return undefined;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Takes a hex encoded pubkey, converts it to the Amino JSON representation (type/value wrapper)
|
|
360
|
+
* and returns it as protobuf `Any`
|
|
361
|
+
* @param {string} pubkey hex encoded compressed secp256k1 public key
|
|
362
|
+
* @returns {Any} pubkey encoded as protobuf `Any`
|
|
363
|
+
*/
|
|
364
|
+
getEncodedPubkey(pubkey) {
|
|
365
|
+
return (0, proto_signing_1.encodePubkey)((0, amino_1.encodeSecp256k1Pubkey)((0, encoding_1.fromHex)(pubkey)));
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Gets the send messages used in the final step of encoding a transaction. This allows for any final processing needed.
|
|
369
|
+
* @param {CosmosLikeTransaction} cosmosLikeTransaction transaction to get send messages from
|
|
370
|
+
* @returns {Any[]} processed send messages
|
|
371
|
+
*/
|
|
372
|
+
getSendMessagesForEncodingTx(cosmosLikeTransaction) {
|
|
373
|
+
return cosmosLikeTransaction.sendMessages;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Creates a txRaw from an cosmos like transaction @see CosmosLikeTransaction
|
|
377
|
+
* @Precondition cosmosLikeTransaction.publicKey must be defined
|
|
378
|
+
* @param {CosmosLikeTransaction} cosmosLikeTransaction
|
|
379
|
+
* @returns {TxRaw} Unsigned raw transaction
|
|
380
|
+
*/
|
|
381
|
+
createTxRawFromCosmosLikeTransaction(cosmosLikeTransaction) {
|
|
382
|
+
if (!cosmosLikeTransaction.publicKey) {
|
|
383
|
+
throw new Error('publicKey is required to create a txRaw');
|
|
384
|
+
}
|
|
385
|
+
const encodedPublicKey = this.getEncodedPubkey(cosmosLikeTransaction.publicKey);
|
|
386
|
+
const messages = this.getSendMessagesForEncodingTx(cosmosLikeTransaction);
|
|
387
|
+
let txBodyValue;
|
|
388
|
+
if (cosmosLikeTransaction.memo) {
|
|
389
|
+
txBodyValue = {
|
|
390
|
+
memo: cosmosLikeTransaction.memo,
|
|
391
|
+
messages: messages,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
txBodyValue = {
|
|
396
|
+
messages: messages,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
const txBodyBytes = this.registry.encodeTxBody(txBodyValue);
|
|
400
|
+
const sequence = cosmosLikeTransaction.sequence;
|
|
401
|
+
const authInfoBytes = (0, proto_signing_1.makeAuthInfoBytes)([{ pubkey: encodedPublicKey, sequence }], cosmosLikeTransaction.gasBudget.amount, cosmosLikeTransaction.gasBudget.gasLimit, undefined, undefined, undefined);
|
|
402
|
+
return tx_1.TxRaw.fromPartial({
|
|
403
|
+
bodyBytes: txBodyBytes,
|
|
404
|
+
authInfoBytes: authInfoBytes,
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Encodes a signature into a txRaw
|
|
409
|
+
* @param {string} publicKeyHex publicKey in hex encoded string format
|
|
410
|
+
* @param {string} signatureHex signature in hex encoded string format
|
|
411
|
+
* @param {TxRaw} unsignedTx raw transaction
|
|
412
|
+
* @returns {TxRaw} Signed raw transaction
|
|
413
|
+
*/
|
|
414
|
+
createSignedTxRaw(publicKeyHex, signatureHex, unsignedTx) {
|
|
415
|
+
const stdSignature = (0, amino_1.encodeSecp256k1Signature)((0, encoding_1.fromHex)(publicKeyHex), (0, encoding_1.fromHex)(signatureHex));
|
|
416
|
+
return tx_1.TxRaw.fromPartial({
|
|
417
|
+
bodyBytes: unsignedTx.bodyBytes,
|
|
418
|
+
authInfoBytes: unsignedTx.authInfoBytes,
|
|
419
|
+
signatures: [(0, encoding_1.fromBase64)(stdSignature.signature)],
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Decodes a raw transaction into a DecodedTxRaw and checks if it has non empty signatures
|
|
424
|
+
* @param {string} rawTransaction
|
|
425
|
+
* @returns {boolean} true if transaction is signed else false
|
|
426
|
+
*/
|
|
427
|
+
isSignedRawTx(rawTransaction) {
|
|
428
|
+
const decodedTx = this.getDecodedTxFromRawBase64(rawTransaction);
|
|
429
|
+
if (decodedTx.signatures.length > 0) {
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Returns whether or not the string is a valid protocol public key
|
|
436
|
+
* @param {string | undefined} publicKey - the public key to be validated
|
|
437
|
+
*/
|
|
438
|
+
validatePublicKey(publicKey) {
|
|
439
|
+
if (publicKey !== undefined) {
|
|
440
|
+
try {
|
|
441
|
+
new keyPair_1.CosmosKeyPair({ pub: publicKey });
|
|
442
|
+
}
|
|
443
|
+
catch {
|
|
444
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid Public Key`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Creates a sign doc from an cosmos like transaction @see CosmosLikeTransaction
|
|
450
|
+
* @Precondition cosmosLikeTransaction.accountNumber and cosmosLikeTransaction.chainId must be defined
|
|
451
|
+
* @param {CosmosLikeTransaction} cosmosLikeTransaction
|
|
452
|
+
* @returns {SignDoc} sign doc
|
|
453
|
+
*/
|
|
454
|
+
createSignDoc(cosmosLikeTransaction, accountNumber, chainId) {
|
|
455
|
+
if (!accountNumber) {
|
|
456
|
+
throw new Error('accountNumber is required to create a sign doc');
|
|
457
|
+
}
|
|
458
|
+
if (!chainId) {
|
|
459
|
+
throw new Error('chainId is required to create a sign doc');
|
|
460
|
+
}
|
|
461
|
+
if (!cosmosLikeTransaction) {
|
|
462
|
+
throw new Error('cosmosLikeTransaction is required to create a sign doc');
|
|
463
|
+
}
|
|
464
|
+
const txRaw = this.createTxRawFromCosmosLikeTransaction(cosmosLikeTransaction);
|
|
465
|
+
return (0, proto_signing_1.makeSignDoc)(txRaw.bodyBytes, txRaw.authInfoBytes, chainId, accountNumber);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Returns whether or not the string is a valid hex
|
|
469
|
+
* @param hexString - hex string format
|
|
470
|
+
* @returns {boolean} true if string is hex else false
|
|
471
|
+
*/
|
|
472
|
+
isValidHexString(hexString) {
|
|
473
|
+
return /^[0-9A-Fa-f]*$/.test(hexString);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Validates the WithdrawDelegatorRewardsMessage
|
|
477
|
+
* @param {WithdrawDelegatorRewardsMessage} withdrawRewardsMessage - The WithdrawDelegatorRewardsMessage to validate.
|
|
478
|
+
* @throws {InvalidTransactionError} Throws an error if the validatorAddress or delegatorAddress is invalid or missing.
|
|
479
|
+
*/
|
|
480
|
+
validateWithdrawRewardsMessage(withdrawRewardsMessage) {
|
|
481
|
+
if (!withdrawRewardsMessage.validatorAddress ||
|
|
482
|
+
!this.isValidValidatorAddress(withdrawRewardsMessage.validatorAddress)) {
|
|
483
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid WithdrawDelegatorRewardsMessage validatorAddress: ` + withdrawRewardsMessage.validatorAddress);
|
|
484
|
+
}
|
|
485
|
+
if (!withdrawRewardsMessage.delegatorAddress || !this.isValidAddress(withdrawRewardsMessage.delegatorAddress)) {
|
|
486
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid WithdrawDelegatorRewardsMessage delegatorAddress: ` + withdrawRewardsMessage.delegatorAddress);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Helper method to check if the specified properties in an object are missing or null.
|
|
491
|
+
* @param {Object} obj - The object to check.
|
|
492
|
+
* @param {string[]} keys - An array of property keys to check.
|
|
493
|
+
* @throws {Error} Throws an error if any of the specified properties are missing or null.
|
|
494
|
+
*/
|
|
495
|
+
isObjPropertyNull(obj, keys) {
|
|
496
|
+
for (const key of keys) {
|
|
497
|
+
if (obj[key] == null) {
|
|
498
|
+
throw new Error(`Missing or null value for property ${key}`);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Validates the DelegateOrUndelegeteMessage
|
|
504
|
+
* @param {DelegateOrUndelegeteMessage} delegateMessage - The DelegateOrUndelegeteMessage to validate.
|
|
505
|
+
* @throws {InvalidTransactionError} Throws an error if the validatorAddress, delegatorAddress, or amount is invalid or missing.
|
|
506
|
+
*/
|
|
507
|
+
validateDelegateOrUndelegateMessage(delegateMessage) {
|
|
508
|
+
this.isObjPropertyNull(delegateMessage, ['validatorAddress', 'delegatorAddress']);
|
|
509
|
+
if (!this.isValidValidatorAddress(delegateMessage.validatorAddress)) {
|
|
510
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid DelegateOrUndelegeteMessage validatorAddress: ` + delegateMessage.validatorAddress);
|
|
511
|
+
}
|
|
512
|
+
if (!this.isValidAddress(delegateMessage.delegatorAddress)) {
|
|
513
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid DelegateOrUndelegeteMessage delegatorAddress: ` + delegateMessage.delegatorAddress);
|
|
514
|
+
}
|
|
515
|
+
this.validateAmount(delegateMessage.amount);
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Validates the RedelegateMessage
|
|
519
|
+
* @param {DelegateOrUndelegeteMessage} redelegateMessage - The RedelegateMessage to validate.
|
|
520
|
+
* @throws {InvalidTransactionError} Throws an error if the validatorSrcAddress, validatorDstAddress, delegatorAddress, or amount is invalid or missing.
|
|
521
|
+
*/
|
|
522
|
+
validateRedelegateMessage(redelegateMessage) {
|
|
523
|
+
this.isObjPropertyNull(redelegateMessage, ['validatorSrcAddress', 'validatorDstAddress', 'delegatorAddress']);
|
|
524
|
+
if (!this.isValidValidatorAddress(redelegateMessage.validatorSrcAddress)) {
|
|
525
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid RedelegateMessage validatorSrcAddress: ` + redelegateMessage.validatorSrcAddress);
|
|
526
|
+
}
|
|
527
|
+
if (!this.isValidValidatorAddress(redelegateMessage.validatorDstAddress)) {
|
|
528
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid RedelegateMessage validatorDstAddress: ` + redelegateMessage.validatorDstAddress);
|
|
529
|
+
}
|
|
530
|
+
if (!this.isValidAddress(redelegateMessage.delegatorAddress)) {
|
|
531
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid DelegateOrUndelegeteMessage delegatorAddress: ` + redelegateMessage.delegatorAddress);
|
|
532
|
+
}
|
|
533
|
+
this.validateAmount(redelegateMessage.amount);
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Validates the CustomMessage
|
|
537
|
+
* @param {CustomMessage} customMessage - The CustomMessage to validate.
|
|
538
|
+
* @throws {InvalidTransactionError} Throws an error if the custom message is invalid or missing required fields.
|
|
539
|
+
* @throws {NotSupported} Throws an error if the custom message data is not supported.
|
|
540
|
+
*/
|
|
541
|
+
validateCustomMessage(customMessage) {
|
|
542
|
+
throw new sdk_core_1.NotSupported('Custom message data not supported');
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Validates the MessageData
|
|
546
|
+
* @param {MessageData} messageData - The MessageData to validate.
|
|
547
|
+
* @throws {InvalidTransactionError} Throws an error if the messageData is invalid or missing required fields.
|
|
548
|
+
*/
|
|
549
|
+
validateMessageData(messageData) {
|
|
550
|
+
if (messageData == null) {
|
|
551
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid MessageData: undefined`);
|
|
552
|
+
}
|
|
553
|
+
if (messageData.typeUrl == null || this.getTransactionTypeFromTypeUrl(messageData.typeUrl) == null) {
|
|
554
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid MessageData typeurl: ` + messageData.typeUrl);
|
|
555
|
+
}
|
|
556
|
+
const type = this.getTransactionTypeFromTypeUrl(messageData.typeUrl);
|
|
557
|
+
switch (type) {
|
|
558
|
+
case sdk_core_1.TransactionType.Send: {
|
|
559
|
+
const value = messageData.value;
|
|
560
|
+
this.validateSendMessage(value);
|
|
561
|
+
break;
|
|
562
|
+
}
|
|
563
|
+
case sdk_core_1.TransactionType.StakingActivate:
|
|
564
|
+
case sdk_core_1.TransactionType.StakingDeactivate: {
|
|
565
|
+
const value = messageData.value;
|
|
566
|
+
this.validateDelegateOrUndelegateMessage(value);
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
case sdk_core_1.TransactionType.StakingWithdraw: {
|
|
570
|
+
const value = messageData.value;
|
|
571
|
+
this.validateWithdrawRewardsMessage(value);
|
|
572
|
+
break;
|
|
573
|
+
}
|
|
574
|
+
case sdk_core_1.TransactionType.ContractCall: {
|
|
575
|
+
const value = messageData.value;
|
|
576
|
+
this.validateExecuteContractMessage(value, sdk_core_1.TransactionType.ContractCall);
|
|
577
|
+
break;
|
|
578
|
+
}
|
|
579
|
+
case sdk_core_1.TransactionType.StakingRedelegate: {
|
|
580
|
+
const value = messageData.value;
|
|
581
|
+
this.validateRedelegateMessage(value);
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
584
|
+
case sdk_core_1.TransactionType.CustomTx: {
|
|
585
|
+
const value = messageData.value;
|
|
586
|
+
this.validateCustomMessage(value);
|
|
587
|
+
break;
|
|
588
|
+
}
|
|
589
|
+
default:
|
|
590
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid MessageData TypeUrl is not supported: ` + messageData.typeUrl);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Validates the Cosmos-like transaction.
|
|
595
|
+
* @param {CosmosLikeTransaction} tx - The transaction to validate.
|
|
596
|
+
* @throws {InvalidTransactionError} Throws an error if the transaction is invalid or missing required fields.
|
|
597
|
+
*/
|
|
598
|
+
validateTransaction(tx) {
|
|
599
|
+
this.validateSequence(tx.sequence);
|
|
600
|
+
this.validateGasBudget(tx.gasBudget);
|
|
601
|
+
this.validatePublicKey(tx.publicKey);
|
|
602
|
+
if (tx.sendMessages === undefined || tx.sendMessages.length === 0) {
|
|
603
|
+
throw new sdk_core_1.InvalidTransactionError('Invalid transaction: messages is required');
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
tx.sendMessages.forEach((message) => this.validateMessageData(message));
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Creates a Cosmos-like transaction.
|
|
611
|
+
* @param {number} sequence - The sender address sequence number for the transaction.
|
|
612
|
+
* @param {MessageData[]} messages - The array of message data for the transaction.
|
|
613
|
+
* @param {FeeData} gasBudget - The fee data for the transaction.
|
|
614
|
+
* @param {string} [publicKey] - The public key associated with the sender.
|
|
615
|
+
* @param {string} [memo] - The memo for the transaction.
|
|
616
|
+
* @returns {CosmosLikeTransaction} Returns the created Cosmos-like transaction.
|
|
617
|
+
* @throws {InvalidTransactionError} Throws an error if the created transaction is invalid.
|
|
618
|
+
*/
|
|
619
|
+
createTransaction(sequence, messages, gasBudget, publicKey, memo) {
|
|
620
|
+
const cosmosLikeTxn = {
|
|
621
|
+
sequence: sequence,
|
|
622
|
+
sendMessages: messages,
|
|
623
|
+
gasBudget: gasBudget,
|
|
624
|
+
publicKey: publicKey,
|
|
625
|
+
memo: memo,
|
|
626
|
+
};
|
|
627
|
+
this.validateTransaction(cosmosLikeTxn);
|
|
628
|
+
return cosmosLikeTxn;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Creates a Cosmos-like transaction with a hash.
|
|
632
|
+
* @param {number} sequence - The sender address sequence number for the transaction.
|
|
633
|
+
* @param {MessageData[]} messages - The array of message data for the transaction.
|
|
634
|
+
* @param {FeeData} gasBudget - The fee data for the transaction.
|
|
635
|
+
* @param {string} [publicKey] - The public key associated with the transaction.
|
|
636
|
+
* @param {Buffer} [signature] - The signature for the transaction.
|
|
637
|
+
* @param {string} [memo] - The memo for the transaction.
|
|
638
|
+
* @returns {CosmosLikeTransaction} Returns the created Cosmos-like transaction with the hash and signature if provided.
|
|
639
|
+
*/
|
|
640
|
+
createTransactionWithHash(sequence, messages, gasBudget, publicKey, signature, memo) {
|
|
641
|
+
const cosmosLikeTxn = this.createTransaction(sequence, messages, gasBudget, publicKey, memo);
|
|
642
|
+
let hash = constants.UNAVAILABLE_TEXT;
|
|
643
|
+
if (signature !== undefined) {
|
|
644
|
+
const unsignedTx = this.createTxRawFromCosmosLikeTransaction(cosmosLikeTxn);
|
|
645
|
+
const signedTx = tx_1.TxRaw.fromPartial({
|
|
646
|
+
bodyBytes: unsignedTx.bodyBytes,
|
|
647
|
+
authInfoBytes: unsignedTx.authInfoBytes,
|
|
648
|
+
signatures: [signature],
|
|
649
|
+
});
|
|
650
|
+
hash = (0, crypto_1.createHash)('sha256')
|
|
651
|
+
.update(tx_1.TxRaw.encode(signedTx).finish())
|
|
652
|
+
.digest()
|
|
653
|
+
.toString('hex')
|
|
654
|
+
.toLocaleUpperCase('en-US');
|
|
655
|
+
return { ...cosmosLikeTxn, hash: hash, signature: signature };
|
|
656
|
+
}
|
|
657
|
+
return { ...cosmosLikeTxn, hash: hash };
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Deserializes base64 enocded raw transaction string into @see CosmosLikeTransaction
|
|
661
|
+
* @param {string} rawTx base64 enocded raw transaction string
|
|
662
|
+
* @returns {CosmosLikeTransaction} Deserialized cosmosLikeTransaction
|
|
663
|
+
*/
|
|
664
|
+
deserializeTransaction(rawTx) {
|
|
665
|
+
const decodedTx = this.getDecodedTxFromRawBase64(rawTx);
|
|
666
|
+
const typeUrl = this.getTypeUrlFromDecodedTx(decodedTx);
|
|
667
|
+
const type = this.getTransactionTypeFromTypeUrl(typeUrl);
|
|
668
|
+
let sendMessageData;
|
|
669
|
+
if (type === sdk_core_1.TransactionType.Send) {
|
|
670
|
+
sendMessageData = this.getSendMessageDataFromDecodedTx(decodedTx);
|
|
671
|
+
}
|
|
672
|
+
else if (type === sdk_core_1.TransactionType.StakingActivate || type === sdk_core_1.TransactionType.StakingDeactivate) {
|
|
673
|
+
sendMessageData = this.getDelegateOrUndelegateMessageDataFromDecodedTx(decodedTx);
|
|
674
|
+
}
|
|
675
|
+
else if (type === sdk_core_1.TransactionType.StakingWithdraw) {
|
|
676
|
+
sendMessageData = this.getWithdrawRewardsMessageDataFromDecodedTx(decodedTx);
|
|
677
|
+
}
|
|
678
|
+
else if (type === sdk_core_1.TransactionType.ContractCall) {
|
|
679
|
+
sendMessageData = this.getExecuteContractMessageDataFromDecodedTx(decodedTx);
|
|
680
|
+
}
|
|
681
|
+
else if (type === sdk_core_1.TransactionType.StakingRedelegate) {
|
|
682
|
+
sendMessageData = this.getRedelegateMessageDataFromDecodedTx(decodedTx);
|
|
683
|
+
}
|
|
684
|
+
else if (type === sdk_core_1.TransactionType.CustomTx) {
|
|
685
|
+
sendMessageData = this.getCustomMessageDataFromDecodedTx(decodedTx);
|
|
686
|
+
}
|
|
687
|
+
else {
|
|
688
|
+
throw new Error('Transaction type not supported: ' + typeUrl);
|
|
689
|
+
}
|
|
690
|
+
const sequence = this.getSequenceFromDecodedTx(decodedTx);
|
|
691
|
+
const gasBudget = this.getGasBudgetFromDecodedTx(decodedTx);
|
|
692
|
+
const publicKey = this.getPublicKeyFromDecodedTx(decodedTx);
|
|
693
|
+
const signature = decodedTx.signatures?.[0] !== undefined ? Buffer.from(decodedTx.signatures[0]) : undefined;
|
|
694
|
+
return this.createTransactionWithHash(sequence, sendMessageData, gasBudget, publicKey, signature, decodedTx.body?.memo);
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Validates an array of coin amounts.
|
|
698
|
+
* @param {Coin[]} amountArray - The array of coin amounts to validate.
|
|
699
|
+
* @param {TransactionType} transactionType - optional field for transaction type
|
|
700
|
+
*/
|
|
701
|
+
validateAmountData(amountArray, transactionType) {
|
|
702
|
+
amountArray.forEach((coinAmount) => {
|
|
703
|
+
this.validateAmount(coinAmount, transactionType);
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Validates the gas limit and gas amount for a transaction.
|
|
708
|
+
* @param {FeeData} gasBudget - The gas budget to validate.
|
|
709
|
+
* @throws {InvalidTransactionError} Throws an error if the gas budget is invalid.
|
|
710
|
+
*/
|
|
711
|
+
validateGasBudget(gasBudget) {
|
|
712
|
+
if (gasBudget.gasLimit <= 0) {
|
|
713
|
+
throw new sdk_core_1.InvalidTransactionError('Invalid gas limit ' + gasBudget.gasLimit);
|
|
714
|
+
}
|
|
715
|
+
this.validateAmountData(gasBudget.amount);
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Validates a send message for a transaction.
|
|
719
|
+
* @param {SendMessage} sendMessage - The send message to validate.
|
|
720
|
+
* @throws {InvalidTransactionError} Throws an error if the send message is invalid.
|
|
721
|
+
*/
|
|
722
|
+
validateSendMessage(sendMessage) {
|
|
723
|
+
if (!sendMessage.toAddress || !this.isValidAddress(sendMessage.toAddress)) {
|
|
724
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid SendMessage toAddress: ` + sendMessage.toAddress);
|
|
725
|
+
}
|
|
726
|
+
if (!sendMessage.fromAddress || !this.isValidAddress(sendMessage.fromAddress)) {
|
|
727
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid SendMessage fromAddress: ` + sendMessage.fromAddress);
|
|
728
|
+
}
|
|
729
|
+
this.validateAmountData(sendMessage.amount);
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Validates a coin amount.
|
|
733
|
+
* @param {Coin} amount - The coin amount to validate.
|
|
734
|
+
* @param {TransactionType} transactionType - optional field for transaction type
|
|
735
|
+
* @throws {InvalidTransactionError} Throws an error if the coin amount is invalid.
|
|
736
|
+
*/
|
|
737
|
+
validateAmount(amount, transactionType) {
|
|
738
|
+
throw new sdk_core_1.NotImplementedError('validateAmount not implemented');
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Checks if a cosmos like Bech32 address matches given regular expression and
|
|
742
|
+
* validates memoId if present
|
|
743
|
+
* @param {string} address
|
|
744
|
+
* @param {RegExp} regExp Regular expression to validate the root address against after trimming the memoId
|
|
745
|
+
* @returns {boolean} true if address is valid
|
|
746
|
+
*/
|
|
747
|
+
isValidCosmosLikeAddressWithMemoId(address, regExp) {
|
|
748
|
+
if (typeof address !== 'string')
|
|
749
|
+
return false;
|
|
750
|
+
const addressArray = address.split('?memoId=');
|
|
751
|
+
if (![1, 2].includes(addressArray.length) || // should have at most one occurrence of 'memoId='
|
|
752
|
+
!this.isValidBech32AddressMatchingRegex(addressArray[0], regExp) ||
|
|
753
|
+
(addressArray[1] && !this.isValidMemoId(addressArray[1]))) {
|
|
754
|
+
return false;
|
|
755
|
+
}
|
|
756
|
+
return true;
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Checks if address is valid Bech32 and matches given regular expression
|
|
760
|
+
* @param {string} address
|
|
761
|
+
* @param {RegExp} regExp Regular expression to validate the address against
|
|
762
|
+
* @returns {boolean} true if address is valid
|
|
763
|
+
*/
|
|
764
|
+
isValidBech32AddressMatchingRegex(address, regExp) {
|
|
765
|
+
try {
|
|
766
|
+
(0, encoding_1.fromBech32)(address);
|
|
767
|
+
}
|
|
768
|
+
catch (e) {
|
|
769
|
+
return false;
|
|
770
|
+
}
|
|
771
|
+
return regExp.test(address);
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Return boolean indicating whether a memo id is valid
|
|
775
|
+
*
|
|
776
|
+
* @param memoId memo id
|
|
777
|
+
* @returns true if memo id is valid
|
|
778
|
+
*/
|
|
779
|
+
isValidMemoId(memoId) {
|
|
780
|
+
// Allow alphanumeric memo IDs (including uppercase and lowercase letters)
|
|
781
|
+
const alphanumericRegex = /^[0-9a-zA-Z]+$/;
|
|
782
|
+
// Check if the memoId is alphanumeric
|
|
783
|
+
if (!alphanumericRegex.test(memoId)) {
|
|
784
|
+
return false;
|
|
785
|
+
}
|
|
786
|
+
// If the memoId is purely numeric, ensure it is a positive integer
|
|
787
|
+
if (/^\d+$/.test(memoId)) {
|
|
788
|
+
const memoIdNumber = new bignumber_js_1.default(memoId);
|
|
789
|
+
return memoIdNumber.gte(0) && memoIdNumber.isInteger();
|
|
790
|
+
}
|
|
791
|
+
return true;
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Validates if the address matches with regex @see accountAddressRegex
|
|
795
|
+
* @param {string} address
|
|
796
|
+
* @returns {boolean} - the validation result
|
|
797
|
+
*/
|
|
798
|
+
isValidValidatorAddress(address) {
|
|
799
|
+
throw new sdk_core_1.NotImplementedError('isValidValidatorAddress not implemented');
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Validates if the address matches with regex @see accountAddressRegex
|
|
803
|
+
* @param {string} address
|
|
804
|
+
* @returns {boolean} - the validation result
|
|
805
|
+
*/
|
|
806
|
+
isValidAddress(address) {
|
|
807
|
+
throw new sdk_core_1.NotImplementedError('isValidAddress not implemented');
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Validates if the address matches with regex @see contractAddressRegex
|
|
811
|
+
* @param {string} address
|
|
812
|
+
* @returns {boolean} - the validation result
|
|
813
|
+
*/
|
|
814
|
+
isValidContractAddress(address) {
|
|
815
|
+
throw new sdk_core_1.NotImplementedError('isValidContractAddress not implemented');
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Validates a execute contract message
|
|
819
|
+
* @param {ExecuteContractMessage} message - The execute contract message to validate
|
|
820
|
+
* @param {TransactionType} transactionType - optional field for transaction type
|
|
821
|
+
* @throws {InvalidTransactionError} Throws an error if the message is invalid
|
|
822
|
+
*/
|
|
823
|
+
validateExecuteContractMessage(message, transactionType) {
|
|
824
|
+
if (!message.contract || !this.isValidContractAddress(message.contract)) {
|
|
825
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid ExecuteContractMessage contract address: ` + message.contract);
|
|
826
|
+
}
|
|
827
|
+
if (!message.sender || !this.isValidAddress(message.sender)) {
|
|
828
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid ExecuteContractMessage sender address: ` + message.sender);
|
|
829
|
+
}
|
|
830
|
+
if (!message.msg) {
|
|
831
|
+
throw new sdk_core_1.InvalidTransactionError(`Invalid ExecuteContractMessage msg: ` + message.msg);
|
|
832
|
+
}
|
|
833
|
+
if (message.funds) {
|
|
834
|
+
this.validateAmountData(message.funds, transactionType);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Get coin specific hash function
|
|
839
|
+
* @returns {Hash} The hash function
|
|
840
|
+
*/
|
|
841
|
+
getHashFunction() {
|
|
842
|
+
return (0, crypto_1.createHash)('sha256');
|
|
843
|
+
}
|
|
844
|
+
getTokenDenomsUsingCoinFamily(coinFamily) {
|
|
845
|
+
// using set to remove duplicates as denom can be same on testnet and mainnet for a few tokens
|
|
846
|
+
return [
|
|
847
|
+
...new Set(statics_1.coins
|
|
848
|
+
.filter((coin) => coin.family.toLowerCase() === coinFamily.toLowerCase() && coin.isToken && coin.denom !== undefined)
|
|
849
|
+
.map((coin) => coin.denom)),
|
|
850
|
+
];
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
exports.CosmosUtils = CosmosUtils;
|
|
854
|
+
const utils = new CosmosUtils();
|
|
855
|
+
exports.default = utils;
|
|
856
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1EQU84QjtBQUM5Qix5Q0FBZ0Y7QUFDaEYsK0NBQW9GO0FBQ3BGLHlEQVMrQjtBQUMvQiwrQ0FBOEQ7QUFDOUQsaURBQTRDO0FBQzVDLGdFQUFxQztBQUNyQywwREFBbUU7QUFFbkUseURBQXNFO0FBQ3RFLG1DQUEwQztBQUMxQyx1REFBeUM7QUFXekMsdUNBQXFEO0FBRXJELE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUMsNkJBQTZCLENBQUMsQ0FBQyxLQUFLLENBQUM7QUFFakUsTUFBYSxXQUFXO0lBR3RCO1FBQ0UsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLHdCQUFRLENBQUMsQ0FBQyxHQUFHLCtCQUFvQixDQUFDLENBQUMsQ0FBQztRQUN4RCxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMseUJBQXlCLEVBQUUsdUJBQWtCLENBQUMsQ0FBQztRQUNoRixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLGNBQWMsQ0FBQyxJQUFZO1FBQ3pCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLGlCQUFpQixDQUFDLEdBQVc7UUFDM0IsSUFBSSxDQUFDO1lBQ0gsSUFBSSx1QkFBTyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDMUIsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQztJ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SSxrQ0FBdUIsQ0FBQyxzQ0FBc0MsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDMUYsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQzFELENBQUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsZUFBZTtRQUNiLE9BQU8sSUFBQSxtQkFBVSxFQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRCw2QkFBNkIsQ0FBQyxVQUFrQjtRQUM5Qyw4RkFBOEY7UUFDOUYsT0FBTztZQUNMLEdBQUcsSUFBSSxHQUFHLENBQ1IsZUFBSztpQkFDRixNQUFNLENBQ0wsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLEtBQUssVUFBVSxDQUFDLFdBQVcsRUFBRSxJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyxTQUFTLENBQzdHO2lCQUNBLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQWUsQ0FBQyxDQUN2QztTQUNGLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUEzNEJELGtDQTI0QkM7QUFFRCxNQUFNLEtBQUssR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO0FBRWhDLGtCQUFlLEtBQUssQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEJhc2VVdGlscyxcbiAgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IsXG4gIE5vdEltcGxlbWVudGVkRXJyb3IsXG4gIE5vdFN1cHBvcnRlZCxcbiAgUGFyc2VUcmFuc2FjdGlvbkVycm9yLFxuICBUcmFuc2FjdGlvblR5cGUsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IGVuY29kZVNlY3AyNTZrMVB1YmtleSwgZW5jb2RlU2VjcDI1NmsxU2lnbmF0dXJlIH0gZnJvbSAnQGNvc21qcy9hbWlubyc7XG5pbXBvcnQgeyBmcm9tQmFzZTY0LCBmcm9tQmVjaDMyLCBmcm9tSGV4LCB0b0JlY2gzMiwgdG9IZXggfSBmcm9tICdAY29zbWpzL2VuY29kaW5nJztcbmltcG9ydCB7XG4gIERlY29kZWRUeFJhdyxcbiAgZGVjb2RlUHVia2V5LFxuICBkZWNvZGVUeFJhdyxcbiAgRW5jb2RlT2JqZWN0LFxuICBlbmNvZGVQdWJrZXksXG4gIG1ha2VBdXRoSW5mb0J5dGVzLFxuICBtYWtlU2lnbkRvYyxcbiAgUmVnaXN0cnksXG59IGZyb20gJ0Bjb3NtanMvcHJvdG8tc2lnbmluZyc7XG5pbXBvcnQgeyBDb2luLCBkZWZhdWx0UmVnaXN0cnlUeXBlcyB9IGZyb20gJ0Bjb3NtanMvc3RhcmdhdGUnO1xuaW1wb3J0IHsgY29pbnMgfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcbmltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7IFNpZ25Eb2MsIFR4UmF3IH0gZnJvbSAnY29zbWpzLXR5cGVzL2Nvc21vcy90eC92MWJldGExL3R4JztcbmltcG9ydCB7IEFueSB9IGZyb20gJ2Nvc21qcy10eXBlcy9nb29nbGUvcHJvdG9idWYvYW55JztcbmltcG9ydCB7IE1zZ0V4ZWN1dGVDb250cmFjdCB9IGZyb20gJ2Nvc21qcy10eXBlcy9jb3Ntd2FzbS93YXNtL3YxL3R4JztcbmltcG9ydCB7IGNyZWF0ZUhhc2gsIEhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7XG4gIENvc21vc0xpa2VUcmFuc2FjdGlvbixcbiAgRGVsZWdhdGVPclVuZGVsZWdldGVNZXNzYWdlLFxuICBFeGVjdXRlQ29udHJhY3RNZXNzYWdlLFxuICBGZWVEYXRhLFxuICBNZXNzYWdlRGF0YSxcbiAgUmVkZWxlZ2F0ZU1lc3NhZ2UsXG4gIFNlbmRNZXNzYWdlLFxuICBXaXRoZHJhd0RlbGVnYXRvclJld2FyZHNNZXNzYWdlLFxufSBmcm9tICcuL2lmYWNlJztcbmltcG9ydCB7IENvc21vc0tleVBhaXIgYXMgS2V5UGFpciB9IGZyb20gJy4va2V5UGFpcic7XG5cbmNvbnN0IHsgTXNnU2VuZCB9ID0gcmVxdWlyZSgnLi4vLi4vcmVzb3VyY2VzL01zZ0NvbXBpbGVkJykudHlwZXM7XG5cbmV4cG9ydCBjbGFzcyBDb3Ntb3NVdGlsczxDdXN0b21NZXNzYWdlID0gbmV2ZXI+IGltcGxlbWVudHMgQmFzZVV0aWxzIHtcbiAgcHJvdGVjdGVkIHJlZ2lzdHJ5O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoWy4uLmRlZmF1bHRSZWdpc3RyeVR5cGVzXSk7XG4gICAgdGhpcy5yZWdpc3RyeS5yZWdpc3Rlcihjb25zdGFudHMuZXhlY3V0ZUNvbnRyYWN0TXNnVHlwZVVybCwgTXNnRXhlY3V0ZUNvbnRyYWN0KTtcbiAgICB0aGlzLnJlZ2lzdHJ5LnJlZ2lzdGVyKCcvdHlwZXMuTXNnU2VuZCcsIE1zZ1NlbmQpO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGlzVmFsaWRCbG9ja0lkKGhhc2g6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnZhbGlkYXRlQmxha2UyYihoYXNoKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkUHJpdmF0ZUtleShrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBuZXcgS2V5UGFpcih7IHBydjoga2V5IH0pO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGlzVmFsaWRQdWJsaWNLZXkoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgbmV3IEtleVBhaXIoeyBwdWI6IGtleSB9KTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkU2lnbmF0dXJlKHNpZ25hdHVyZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ2lzVmFsaWRTaWduYXR1cmUgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgaXNWYWxpZFRyYW5zYWN0aW9uSWQodHhJZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdGVCbGFrZTJiKHR4SWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0cmFuc2FjdGlvbiBoYXNoIGlzIGluIHZhbGlkIGJsYWNrMmIgZm9ybWF0XG4gICAqL1xuICB2YWxpZGF0ZUJsYWtlMmIoaGFzaDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKGhhc2g/Lmxlbmd0aCAhPT0gNjQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIGhhc2gubWF0Y2goL15bYS16QS1aMC05XSskLykgIT09IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHdoZXRoZXIgYW1vdW50cyBhcmUgaW4gcmFuZ2VcbiAgICpcbiAgICogQHBhcmFtIHtudW1iZXJbXX0gYW1vdW50cyAtIHRoZSBhbW91bnRzIHRvIHZhbGlkYXRlXG4gICAqIEByZXR1cm5zIHtib29sZWFufSAtIHRoZSB2YWxpZGF0aW9uIHJlc3VsdFxuICAgKi9cbiAgaXNWYWxpZEFtb3VudHMoYW1vdW50czogbnVtYmVyW10pOiBib29sZWFuIHtcbiAgICBmb3IgKGNvbnN0IGFtb3VudCBvZiBhbW91bnRzKSB7XG4gICAgICBpZiAoIXRoaXMuaXNWYWxpZEFtb3VudChhbW91bnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHdoZXRoZXIgYW1vdW50IGlzIGluIHJhbmdlXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBhbW91bnRcbiAgICogQHJldHVybnMge2Jvb2xlYW59IHRoZSB2YWxpZGF0aW9uIHJlc3VsdFxuICAgKi9cbiAgaXNWYWxpZEFtb3VudChhbW91bnQ6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGJpZ051bWJlckFtb3VudCA9IG5ldyBCaWdOdW1iZXIoYW1vdW50KTtcbiAgICBpZiAoIWJpZ051bWJlckFtb3VudC5pc0ludGVnZXIoKSB8fCBiaWdOdW1iZXJBbW91bnQuaXNMZXNzVGhhbk9yRXF1YWxUbygwKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNvZGVzIHJhdyB0eCBkYXRhIGludG8gbWVzc2FnZXMsIHNpZ25pbmcgaW5mbywgYW5kIGZlZSBkYXRhXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0eEhleCAtIHJhdyBiYXNlNjQgdHhcbiAgICogQHJldHVybnMge0RlY29kZWRUeFJhd30gRGVjb2RlZCB0cmFuc2FjdGlvblxuICAgKi9cbiAgZ2V0RGVjb2RlZFR4RnJvbVJhd0Jhc2U2NCh0eFJhdzogc3RyaW5nKTogRGVjb2RlZFR4UmF3IHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGRlY29kZVR4UmF3KGZyb21CYXNlNjQodHhSYXcpKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2VUcmFuc2FjdGlvbkVycm9yKCdFcnJvciBkZWNvZGluZyBUeFJhdyBiYXNlNjQgZW5jb2RlZCBzdHJpbmc6ICcgKyBlLm1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhcnJheSBvZiBtZXNzYWdlcyBpbiB0aGUgYm9keSBvZiB0aGUgZGVjb2RlZCB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge0RlY29kZWRUeFJhd30gZGVjb2RlZFR4XG4gICAqIEByZXR1cm5zIHtFbmNvZGVPYmplY3RbXX0gbWVzc2FnZXMgYWxvbmcgd2l0aCB0eXBlIHVybFxuICAgKi9cbiAgcHJpdmF0ZSBnZXRFbmNvZGVkTWVzc2FnZXNGcm9tRGVjb2RlZFR4KGRlY29kZWRUeDogRGVjb2RlZFR4UmF3KTogRW5jb2RlT2JqZWN0W10ge1xuICAgIHJldHVybiBkZWNvZGVkVHguYm9keS5tZXNzYWdlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgdGhlIHR4biBzZXF1ZW5jZSBpcyB2YWxpZCBvciBub3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNlcXVlbmNlXG4gICAqL1xuICB2YWxpZGF0ZVNlcXVlbmNlKHNlcXVlbmNlOiBudW1iZXIpIHtcbiAgICBpZiAoc2VxdWVuY2UgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgc2VxdWVuY2U6IGxlc3MgdGhhbiB6ZXJvJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFB1bGxzIHRoZSBzZXF1ZW5jZSBudW1iZXIgZnJvbSBhIERlY29kZWRUeFJhdyBBdXRoSW5mbyBwcm9wZXJ0eVxuICAgKiBAcGFyYW0ge0RlY29kZWRUeFJhd30gZGVjb2RlZFR4XG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IHNlcXVlbmNlXG4gICAqL1xuICBnZXRTZXF1ZW5jZUZyb21EZWNvZGVkVHgoZGVjb2RlZFR4OiBEZWNvZGVkVHhSYXcpOiBudW1iZXIge1xuICAgIHJldHVybiBOdW1iZXIoZGVjb2RlZFR4LmF1dGhJbmZvLnNpZ25lckluZm9zWzBdLnNlcXVlbmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWxscyB0aGUgdHlwZVVybCBmcm9tIHRoZSBlbmNvZGVkIG1lc3NhZ2Ugb2YgYSBEZWNvZGVkVHhSYXdcbiAgICogQHBhcmFtIHtEZWNvZGVkVHhSYXd9IGRlY29kZWRUeFxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBjb3Ntb3MgcHJvdG8gdHlwZSB1cmxcbiAgICovXG4gIGdldFR5cGVVcmxGcm9tRGVjb2RlZFR4KGRlY29kZWRUeDogRGVjb2RlZFR4UmF3KTogc3RyaW5nIHtcbiAgICBjb25zdCBlbmNvZGVkTWVzc2FnZSA9IHRoaXMuZ2V0RW5jb2RlZE1lc3NhZ2VzRnJvbURlY29kZWRUeChkZWNvZGVkVHgpWzBdO1xuICAgIHJldHVybiBlbmNvZGVkTWVzc2FnZS50eXBlVXJsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGZlZSBkYXRhIGZyb20gdGhlIGRlY29kZWQgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtEZWNvZGVkVHhSYXd9IGRlY29kZWRUeFxuICAgKiBAcmV0dXJucyB7RmVlRGF0YX0gZmVlIGRhdGFcbiAgICovXG4gIGdldEdhc0J1ZGdldEZyb21EZWNvZGVkVHgoZGVjb2RlZFR4OiBEZWNvZGVkVHhSYXcpOiBGZWVEYXRhIHtcbiAgICByZXR1cm4ge1xuICAgICAgYW1vdW50OiBkZWNvZGVkVHguYXV0aEluZm8uZmVlPy5hbW91bnQgYXMgQ29pbltdLFxuICAgICAgZ2FzTGltaXQ6IE51bWJlcihkZWNvZGVkVHguYXV0aEluZm8uZmVlPy5nYXNMaW1pdCksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBwdWJsaWNLZXkgZnJvbSB0aGUgZGVjb2RlZCB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge0RlY29kZWRUeFJhd30gZGVjb2RlZFR4XG4gICAqIEByZXR1cm5zIHtzdHJpbmcgfCB1bmRlZmluZWR9IHB1YmxpY0tleSBpbiBoZXggZm9ybWF0IGlmIGl0IGV4aXN0cywgdW5kZWZpbmVkIG90aGVyd2lzZVxuICAgKi9cbiAgZ2V0UHVibGljS2V5RnJvbURlY29kZWRUeChkZWNvZGVkVHg6IERlY29kZWRUeFJhdyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgcHVibGljS2V5VUludDhBcnJheSA9IGRlY29kZWRUeC5hdXRoSW5mby5zaWduZXJJbmZvcz8uWzBdLnB1YmxpY0tleT8udmFsdWU7XG4gICAgaWYgKHB1YmxpY0tleVVJbnQ4QXJyYXkpIHtcbiAgICAgIHJldHVybiB0b0hleChmcm9tQmFzZTY0KGRlY29kZVB1YmtleShkZWNvZGVkVHguYXV0aEluZm8uc2lnbmVySW5mb3M/LlswXS5wdWJsaWNLZXkpPy52YWx1ZSkpO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGFycmF5IG9mIE1lc3NhZ2VEYXRhW10gZnJvbSB0aGUgZGVjb2RlZCB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge0RlY29kZWRUeFJhd30gZGVjb2RlZFR4XG4gICAqIEByZXR1cm5zIHtNZXNzYWdlRGF0YVtdfSBTZW5kIHRyYW5zYWN0aW9uIG1lc3NhZ2UgZGF0YVxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFNlbmRNZXNzYWdlRGF0YUZyb21EZWNvZGVkVHgoZGVjb2RlZFR4OiBEZWNvZGVkVHhSYXcpOiBNZXNzYWdlRGF0YTxDdXN0b21NZXNzYWdlPltdIHtcbiAgICByZXR1cm4gZGVjb2RlZFR4LmJvZHkubWVzc2FnZXMubWFwKChtZXNzYWdlKSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZSA9IHRoaXMucmVnaXN0cnkuZGVjb2RlKG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsdWU6IHtcbiAgICAgICAgICBmcm9tQWRkcmVzczogdmFsdWUuZnJvbUFkZHJlc3MsXG4gICAgICAgICAgdG9BZGRyZXNzOiB2YWx1ZS50b0FkZHJlc3MsXG4gICAgICAgICAgYW1vdW50OiB2YWx1ZS5hbW91bnQsXG4gICAgICAgIH0sXG4gICAgICAgIHR5cGVVcmw6IG1lc3NhZ2UudHlwZVVybCxcbiAgICAgIH07XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXJyYXkgb2YgTWVzc2FnZURhdGFbXSBmcm9tIHRoZSBkZWNvZGVkIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSB7RGVjb2RlZFR4UmF3fSBkZWNvZGVkVHhcbiAgICogQHJldHVybnMge01lc3NhZ2VEYXRhW119IERlbGVnYXRlIG9mIHVuZGVsZWdhdGUgdHJhbnNhY3Rpb24gbWVzc2FnZSBkYXRhXG4gICAqL1xuICBnZXREZWxlZ2F0ZU9yVW5kZWxlZ2F0ZU1lc3NhZ2VEYXRhRnJvbURlY29kZWRUeChkZWNvZGVkVHg6IERlY29kZWRUeFJhdyk6IE1lc3NhZ2VEYXRhPEN1c3RvbU1lc3NhZ2U+W10ge1xuICAgIHJldHVybiBkZWNvZGVkVHguYm9keS5tZXNzYWdlcy5tYXAoKG1lc3NhZ2UpID0+IHtcbiAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5yZWdpc3RyeS5kZWNvZGUobWVzc2FnZSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2YWx1ZToge1xuICAgICAgICAgIGRlbGVnYXRvckFkZHJlc3M6IHZhbHVlLmRlbGVnYXRvckFkZHJlc3MsXG4gICAgICAgICAgdmFsaWRhdG9yQWRkcmVzczogdmFsdWUudmFsaWRhdG9yQWRkcmVzcyxcbiAgICAgICAgICBhbW91bnQ6IHZhbHVlLmFtb3VudCxcbiAgICAgICAgfSxcbiAgICAgICAgdHlwZVVybDogbWVzc2FnZS50eXBlVXJsLFxuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhcnJheSBvZiBNZXNzYWdlRGF0YVtdIGZyb20gdGhlIGRlY29kZWQgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtEZWNvZGVkVHhSYXd9IGRlY29kZWRUeFxuICAgKiBAcmV0dXJucyB7TWVzc2FnZURhdGFbXX0gUmVkZWxlZ2F0ZSB0cmFuc2FjdGlvbiBtZXNzYWdlIGRhdGFcbiAgICovXG4gIGdldFJlZGVsZWdhdGVNZXNzYWdlRGF0YUZyb21EZWNvZGVkVHgoZGVjb2RlZFR4OiBEZWNvZGVkVHhSYXcpOiBNZXNzYWdlRGF0YTxDdXN0b21NZXNzYWdlPltdIHtcbiAgICByZXR1cm4gZGVjb2RlZFR4LmJvZHkubWVzc2FnZXMubWFwKChtZXNzYWdlKSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZSA9IHRoaXMucmVnaXN0cnkuZGVjb2RlKG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsdWU6IHtcbiAgICAgICAgICBkZWxlZ2F0b3JBZGRyZXNzOiB2YWx1ZS5kZWxlZ2F0b3JBZGRyZXNzLFxuICAgICAgICAgIHZhbGlkYXRvclNyY0FkZHJlc3M6IHZhbHVlLnZhbGlkYXRvclNyY0FkZHJlc3MsXG4gICAgICAgICAgdmFsaWRhdG9yRHN0QWRkcmVzczogdmFsdWUudmFsaWRhdG9yRHN0QWRkcmVzcyxcbiAgICAgICAgICBhbW91bnQ6IHZhbHVlLmFtb3VudCxcbiAgICAgICAgfSxcbiAgICAgICAgdHlwZVVybDogbWVzc2FnZS50eXBlVXJsLFxuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhcnJheSBvZiBNZXNzYWdlRGF0YVtdIGZyb20gdGhlIGRlY29kZWQgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtEZWNvZGVkVHhSYXd9IGRlY29kZWRUeFxuICAgKiBAcmV0dXJucyB7TWVzc2FnZURhdGFbXX0gV2l0aGRyYXdEZWxlZ2F0b3JSZXdhcmRzIHRyYW5zYWN0aW9uIG1lc3NhZ2UgZGF0YVxuICAgKi9cbiAgZ2V0V2l0aGRyYXdSZXdhcmRzTWVzc2FnZURhdGFGcm9tRGVjb2RlZFR4KGRlY29kZWRUeDogRGVjb2RlZFR4UmF3KTogTWVzc2FnZURhdGE8Q3VzdG9tTWVzc2FnZT5bXSB7XG4gICAgcmV0dXJuIGRlY29kZWRUeC5ib2R5Lm1lc3NhZ2VzLm1hcCgobWVzc2FnZSkgPT4ge1xuICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnJlZ2lzdHJ5LmRlY29kZShtZXNzYWdlKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgZGVsZWdhdG9yQWRkcmVzczogdmFsdWUuZGVsZWdhdG9yQWRkcmVzcyxcbiAgICAgICAgICB2YWxpZGF0b3JBZGRyZXNzOiB2YWx1ZS52YWxpZGF0b3JBZGRyZXNzLFxuICAgICAgICB9LFxuICAgICAgICB0eXBlVXJsOiBtZXNzYWdlLnR5cGVVcmwsXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGFycmF5IG9mIE1lc3NhZ2VEYXRhW10gZnJvbSB0aGUgZGVjb2RlZCB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge0RlY29kZWRUeFJhd30gZGVjb2RlZFR4XG4gICAqIEByZXR1cm5zIHtNZXNzYWdlRGF0YVtdfSBEZWxlZ2F0ZSBvZiB1bmRlbGVnYXRlIHRyYW5zYWN0aW9uIG1lc3NhZ2UgZGF0YVxuICAgKi9cbiAgZ2V0V2l0aGRyYXdEZWxlZ2F0b3JSZXdhcmRzTWVzc2FnZURhdGFGcm9tRGVjb2RlZFR4KGRlY29kZWRUeDogRGVjb2RlZFR4UmF3KTogTWVzc2FnZURhdGE8Q3VzdG9tTWVzc2FnZT5bXSB7XG4gICAgcmV0dXJuIGRlY29kZWRUeC5ib2R5Lm1lc3NhZ2VzLm1hcCgobWVzc2FnZSkgPT4ge1xuICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnJlZ2lzdHJ5LmRlY29kZShtZXNzYWdlKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgZGVsZWdhdG9yQWRkcmVzczogdmFsdWUuZGVsZWdhdG9yQWRkcmVzcyxcbiAgICAgICAgICB2YWxpZGF0b3JBZGRyZXNzOiB2YWx1ZS52YWxpZGF0b3JBZGRyZXNzLFxuICAgICAgICB9LFxuICAgICAgICB0eXBlVXJsOiBtZXNzYWdlLnR5cGVVcmwsXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIGNvc21vcyBjaGFpbiBhZGRyZXNzIGZyb20gaXRzIGVxdWl2YWxlbnQgaGV4XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcmVmaXhcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3NIZXhcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIGdldENvc21vc0xpa2VBZGRyZXNzRnJvbUhleChwcmVmaXg6IHN0cmluZywgYWRkcmVzc0hleDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoYWRkcmVzc0hleC5pbmRleE9mKCcweCcpID09PSAwKSB7XG4gICAgICBhZGRyZXNzSGV4ID0gYWRkcmVzc0hleC5zbGljZSgyKTtcbiAgICB9XG4gICAgcmV0dXJuIHRvQmVjaDMyKHByZWZpeCwgZnJvbUhleChhZGRyZXNzSGV4KSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGEgRVZNIGNoYWluIGFkZHJlc3MgZnJvbSBpdHMgZXF1aXZhbGVudCBoZXhcbiAgICogQHBhcmFtIHtzdHJpbmd9IHByZWZpeFxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzc0hleFxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgZ2V0RXZtTGlrZUFkZHJlc3NGcm9tQ29zbW9zKGNvc21vc0xpa2VBZGRyZXNzOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiAnMHgnICsgdG9IZXgoZnJvbUJlY2gzMihjb3Ntb3NMaWtlQWRkcmVzcykuZGF0YSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXJyYXkgb2YgTWVzc2FnZURhdGFbXSBmcm9tIHRoZSBkZWNvZGVkIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSB7RGVjb2RlZFR4UmF3fSBkZWNvZGVkVHhcbiAgICogQHJldHVybnMge01lc3NhZ2VEYXRhW119IEV4ZWN1dGUgY29udHJhY3QgdHJhbnNhY3Rpb24gbWVzc2FnZSBkYXRhXG4gICAqL1xuICBnZXRFeGVjdXRlQ29udHJhY3RNZXNzYWdlRGF0YUZyb21EZWNvZGVkVHgoZGVjb2RlZFR4OiBEZWNvZGVkVHhSYXcpOiBNZXNzYWdlRGF0YTxDdXN0b21NZXNzYWdlPltdIHtcbiAgICByZXR1cm4gZGVjb2RlZFR4LmJvZHkubWVzc2FnZXMubWFwKChtZXNzYWdlKSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZSA9IHRoaXMucmVnaXN0cnkuZGVjb2RlKG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsdWU6IHtcbiAgICAgICAgICBzZW5kZXI6IHZhbHVlLnNlbmRlcixcbiAgICAgICAgICBjb250cmFjdDogdmFsdWUuY29udHJhY3QsXG4gICAgICAgICAgbXNnOiB2YWx1ZS5tc2csXG4gICAgICAgICAgZnVuZHM6IHZhbHVlLmZ1bmRzLFxuICAgICAgICB9LFxuICAgICAgICB0eXBlVXJsOiBtZXNzYWdlLnR5cGVVcmwsXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGFycmF5IG9mIE1lc3NhZ2VEYXRhW10gZnJvbSB0aGUgZGVjb2RlZCB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge0RlY29kZWRUeFJhd30gZGVjb2RlZFR4XG4gICAqIEByZXR1cm5zIHtNZXNzYWdlRGF0YVtdfSBDdXN0b20gdHJhbnNhY3Rpb24gbWVzc2FnZSBkYXRhXG4gICAqL1xuICBnZXRDdXN0b21NZXNzYWdlRGF0YUZyb21EZWNvZGVkVHgoZGVjb2RlZFR4OiBEZWNvZGVkVHhSYXcpOiBNZXNzYWdlRGF0YTxDdXN0b21NZXNzYWdlPltdIHtcbiAgICB0aHJvdyBuZXcgTm90U3VwcG9ydGVkKCdDdXN0b20gbWVzc2FnZSBkYXRhIG5vdCBzdXBwb3J0ZWQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIGJpdGdvIHRyYW5zYWN0aW9uIHR5cGUgYmFzZWQgb24gY29zbW9zIHByb3RvIHR5cGUgdXJsXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlVXJsXG4gICAqIEByZXR1cm5zIHtUcmFuc2FjdGlvblR5cGUgfCB1bmRlZmluZWR9IFRyYW5zYWN0aW9uVHlwZSBpZiB1cmwgaXMgc3VwcG9ydGVkIGVsc2UgdW5kZWZpbmVkXG4gICAqL1xuICBnZXRUcmFuc2FjdGlvblR5cGVGcm9tVHlwZVVybCh0eXBlVXJsOiBzdHJpbmcpOiBUcmFuc2FjdGlvblR5cGUgfCB1bmRlZmluZWQge1xuICAgIHN3aXRjaCAodHlwZVVybCkge1xuICAgICAgY2FzZSBjb25zdGFudHMuc2VuZE1zZ1R5cGVVcmw6XG4gICAgICAgIHJldHVybiBUcmFuc2FjdGlvblR5cGUuU2VuZDtcbiAgICAgIGNhc2UgY29uc3RhbnRzLnNlbmRNc2dUeXBlOlxuICAgICAgICByZXR1cm4gVHJhbnNhY3Rpb25UeXBlLlNlbmQ7XG4gICAgICBjYXNlIGNvbnN0YW50cy5kZWxlZ2F0ZU1zZ1R5cGVVcmw6XG4gICAgICAgIHJldHVybiBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0FjdGl2YXRlO1xuICAgICAgY2FzZSBjb25zdGFudHMudW5kZWxlZ2F0ZU1zZ1R5cGVVcmw6XG4gICAgICAgIHJldHVybiBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0RlYWN0aXZhdGU7XG4gICAgICBjYXNlIGNvbnN0YW50cy53aXRoZHJhd0RlbGVnYXRvclJld2FyZE1zZ1R5cGVVcmw6XG4gICAgICAgIHJldHVybiBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ1dpdGhkcmF3O1xuICAgICAgY2FzZSBjb25zdGFudHMuZXhlY3V0ZUNvbnRyYWN0TXNnVHlwZVVybDpcbiAgICAgICAgcmV0dXJuIFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGw7XG4gICAgICBjYXNlIGNvbnN0YW50cy5yZWRlbGVnYXRlVHlwZVVybDpcbiAgICAgICAgcmV0dXJuIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nUmVkZWxlZ2F0ZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRha2VzIGEgaGV4IGVuY29kZWQgcHVia2V5LCBjb252ZXJ0cyBpdCB0byB0aGUgQW1pbm8gSlNPTiByZXByZXNlbnRhdGlvbiAodHlwZS92YWx1ZSB3cmFwcGVyKVxuICAgKiBhbmQgcmV0dXJucyBpdCBhcyBwcm90b2J1ZiBgQW55YFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHVia2V5IGhleCBlbmNvZGVkIGNvbXByZXNzZWQgc2VjcDI1NmsxIHB1YmxpYyBrZXlcbiAgICogQHJldHVybnMge0FueX0gcHVia2V5IGVuY29kZWQgYXMgcHJvdG9idWYgYEFueWBcbiAgICovXG4gIGdldEVuY29kZWRQdWJrZXkocHVia2V5OiBzdHJpbmcpOiBBbnkge1xuICAgIHJldHVybiBlbmNvZGVQdWJrZXkoZW5jb2RlU2VjcDI1NmsxUHVia2V5KGZyb21IZXgocHVia2V5KSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHNlbmQgbWVzc2FnZXMgdXNlZCBpbiB0aGUgZmluYWwgc3RlcCBvZiBlbmNvZGluZyBhIHRyYW5zYWN0aW9uLiBUaGlzIGFsbG93cyBmb3IgYW55IGZpbmFsIHByb2Nlc3NpbmcgbmVlZGVkLlxuICAgKiBAcGFyYW0ge0Nvc21vc0xpa2VUcmFuc2FjdGlvbn0gY29zbW9zTGlrZVRyYW5zYWN0aW9uIHRyYW5zYWN0aW9uIHRvIGdldCBzZW5kIG1lc3NhZ2VzIGZyb21cbiAgICogQHJldHVybnMge0FueVtdfSBwcm9jZXNzZWQgc2VuZCBtZXNzYWdlc1xuICAgKi9cbiAgZ2V0U2VuZE1lc3NhZ2VzRm9yRW5jb2RpbmdUeChjb3Ntb3NMaWtlVHJhbnNhY3Rpb246IENvc21vc0xpa2VUcmFuc2FjdGlvbjxDdXN0b21NZXNzYWdlPik6IEFueVtdIHtcbiAgICByZXR1cm4gY29zbW9zTGlrZVRyYW5zYWN0aW9uLnNlbmRNZXNzYWdlcyBhcyB1bmtub3duIGFzIEFueVtdO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSB0eFJhdyBmcm9tIGFuIGNvc21vcyBsaWtlIHRyYW5zYWN0aW9uIEBzZWUgQ29zbW9zTGlrZVRyYW5zYWN0aW9uXG4gICAqIEBQcmVjb25kaXRpb24gY29zbW9zTGlrZVRyYW5zYWN0aW9uLnB1YmxpY0tleSBtdXN0IGJlIGRlZmluZWRcbiAgICogQHBhcmFtIHtDb3Ntb3NMaWtlVHJhbnNhY3Rpb259IGNvc21vc0xpa2VUcmFuc2FjdGlvblxuICAgKiBAcmV0dXJucyB7VHhSYXd9IFVuc2lnbmVkIHJhdyB0cmFuc2FjdGlvblxuICAgKi9cbiAgY3JlYXRlVHhSYXdGcm9tQ29zbW9zTGlrZVRyYW5zYWN0aW9uKGNvc21vc0xpa2VUcmFuc2FjdGlvbjogQ29zbW9zTGlrZVRyYW5zYWN0aW9uPEN1c3RvbU1lc3NhZ2U+KTogVHhSYXcge1xuICAgIGlmICghY29zbW9zTGlrZVRyYW5zYWN0aW9uLnB1YmxpY0tleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdwdWJsaWNLZXkgaXMgcmVxdWlyZWQgdG8gY3JlYXRlIGEgdHhSYXcnKTtcbiAgICB9XG4gICAgY29uc3QgZW5jb2RlZFB1YmxpY0tleTogQW55ID0gdGhpcy5nZXRFbmNvZGVkUHVia2V5KGNvc21vc0xpa2VUcmFuc2FjdGlvbi5wdWJsaWNLZXkpO1xuICAgIGNvbnN0IG1lc3NhZ2VzID0gdGhpcy5nZXRTZW5kTWVzc2FnZXNGb3JFbmNvZGluZ1R4KGNvc21vc0xpa2VUcmFuc2FjdGlvbik7XG4gICAgbGV0IHR4Qm9keVZhbHVlO1xuICAgIGlmIChjb3Ntb3NMaWtlVHJhbnNhY3Rpb24ubWVtbykge1xuICAgICAgdHhCb2R5VmFsdWUgPSB7XG4gICAgICAgIG1lbW86IGNvc21vc0xpa2VUcmFuc2FjdGlvbi5tZW1vLFxuICAgICAgICBtZXNzYWdlczogbWVzc2FnZXMsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICB0eEJvZHlWYWx1ZSA9IHtcbiAgICAgICAgbWVzc2FnZXM6IG1lc3NhZ2VzLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCB0eEJvZHlCeXRlcyA9IHRoaXMucmVnaXN0cnkuZW5jb2RlVHhCb2R5KHR4Qm9keVZhbHVlKTtcbiAgICBjb25zdCBzZXF1ZW5jZSA9IGNvc21vc0xpa2VUcmFuc2FjdGlvbi5zZXF1ZW5jZTtcbiAgICBjb25zdCBhdXRoSW5mb0J5dGVzID0gbWFrZUF1dGhJbmZvQnl0ZXMoXG4gICAgICBbeyBwdWJrZXk6IGVuY29kZWRQdWJsaWNLZXksIHNlcXVlbmNlIH1dLFxuICAgICAgY29zbW9zTGlrZVRyYW5zYWN0aW9uLmdhc0J1ZGdldC5hbW91bnQsXG4gICAgICBjb3Ntb3NMaWtlVHJhbnNhY3Rpb24uZ2FzQnVkZ2V0Lmdhc0xpbWl0LFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdW5kZWZpbmVkXG4gICAgKTtcbiAgICByZXR1cm4gVHhSYXcuZnJvbVBhcnRpYWwoe1xuICAgICAgYm9keUJ5dGVzOiB0eEJvZHlCeXRlcyxcbiAgICAgIGF1dGhJbmZvQnl0ZXM6IGF1dGhJbmZvQnl0ZXMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRW5jb2RlcyBhIHNpZ25hdHVyZSBpbnRvIGEgdHhSYXdcbiAgICogQHBhcmFtIHtzdHJpbmd9IHB1YmxpY0tleUhleCBwdWJsaWNLZXkgaW4gaGV4IGVuY29kZWQgc3RyaW5nIGZvcm1hdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gc2lnbmF0dXJlSGV4IHNpZ25hdHVyZSBpbiBoZXggZW5jb2RlZCBzdHJpbmcgZm9ybWF0XG4gICAqIEBwYXJhbSB7VHhSYXd9IHVuc2lnbmVkVHggcmF3IHRyYW5zYWN0aW9uXG4gICAqIEByZXR1cm5zIHtUeFJhd30gU2lnbmVkIHJhdyB0cmFuc2FjdGlvblxuICAgKi9cbiAgY3JlYXRlU2lnbmVkVHhSYXcoXG4gICAgcHVibGljS2V5SGV4OiBzdHJpbmcsXG4gICAgc2lnbmF0dXJlSGV4OiBzdHJpbmcsXG4gICAgdW5zaWduZWRUeDogeyBib2R5Qnl0ZXM6IFVpbnQ4QXJyYXk7IGF1dGhJbmZvQnl0ZXM6IFVpbnQ4QXJyYXkgfVxuICApOiBUeFJhdyB7XG4gICAgY29uc3Qgc3RkU2lnbmF0dXJlID0gZW5jb2RlU2VjcDI1NmsxU2lnbmF0dXJlKGZyb21IZXgocHVibGljS2V5SGV4KSwgZnJvbUhleChzaWduYXR1cmVIZXgpKTtcbiAgICByZXR1cm4gVHhSYXcuZnJvbVBhcnRpYWwoe1xuICAgICAgYm9keUJ5dGVzOiB1bnNpZ25lZFR4LmJvZHlCeXRlcyxcbiAgICAgIGF1dGhJbmZvQnl0ZXM6IHVuc2lnbmVkVHguYXV0aEluZm9CeXRlcyxcbiAgICAgIHNpZ25hdHVyZXM6IFtmcm9tQmFzZTY0KHN0ZFNpZ25hdHVyZS5zaWduYXR1cmUpXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNvZGVzIGEgcmF3IHRyYW5zYWN0aW9uIGludG8gYSBEZWNvZGVkVHhSYXcgYW5kIGNoZWNrcyBpZiBpdCBoYXMgbm9uIGVtcHR5IHNpZ25hdHVyZXNcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJhd1RyYW5zYWN0aW9uXG4gICAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIHRyYW5zYWN0aW9uIGlzIHNpZ25lZCBlbHNlIGZhbHNlXG4gICAqL1xuICBpc1NpZ25lZFJhd1R4KHJhd1RyYW5zYWN0aW9uOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBkZWNvZGVkVHggPSB0aGlzLmdldERlY29kZWRUeEZyb21SYXdCYXNlNjQocmF3VHJhbnNhY3Rpb24pO1xuICAgIGlmIChkZWNvZGVkVHguc2lnbmF0dXJlcy5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHN0cmluZyBpcyBhIHZhbGlkIHByb3RvY29sIHB1YmxpYyBrZXlcbiAgICogQHBhcmFtIHtzdHJpbmcgfCB1bmRlZmluZWR9IHB1YmxpY0tleSAtIHRoZSAgcHVibGljIGtleSB0byBiZSB2YWxpZGF0ZWRcbiAgICovXG4gIHZhbGlkYXRlUHVibGljS2V5KHB1YmxpY0tleTogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgaWYgKHB1YmxpY0tleSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0cnkge1xuICAgICAgICBuZXcgS2V5UGFpcih7IHB1YjogcHVibGljS2V5IH0pO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBQdWJsaWMgS2V5YCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBzaWduIGRvYyBmcm9tIGFuIGNvc21vcyBsaWtlIHRyYW5zYWN0aW9uIEBzZWUgQ29zbW9zTGlrZVRyYW5zYWN0aW9uXG4gICAqIEBQcmVjb25kaXRpb24gY29zbW9zTGlrZVRyYW5zYWN0aW9uLmFjY291bnROdW1iZXIgYW5kIGNvc21vc0xpa2VUcmFuc2FjdGlvbi5jaGFpbklkIG11c3QgYmUgZGVmaW5lZFxuICAgKiBAcGFyYW0ge0Nvc21vc0xpa2VUcmFuc2FjdGlvbn0gY29zbW9zTGlrZVRyYW5zYWN0aW9uXG4gICAqIEByZXR1cm5zIHtTaWduRG9jfSBzaWduIGRvY1xuICAgKi9cbiAgY3JlYXRlU2lnbkRvYyhcbiAgICBjb3Ntb3NMaWtlVHJhbnNhY3Rpb246IENvc21vc0xpa2VUcmFuc2FjdGlvbjxDdXN0b21NZXNzYWdlPixcbiAgICBhY2NvdW50TnVtYmVyOiBudW1iZXIgfCB1bmRlZmluZWQsXG4gICAgY2hhaW5JZDogc3RyaW5nIHwgdW5kZWZpbmVkXG4gICk6IFNpZ25Eb2Mge1xuICAgIGlmICghYWNjb3VudE51bWJlcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdhY2NvdW50TnVtYmVyIGlzIHJlcXVpcmVkIHRvIGNyZWF0ZSBhIHNpZ24gZG9jJyk7XG4gICAgfVxuICAgIGlmICghY2hhaW5JZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjaGFpbklkIGlzIHJlcXVpcmVkIHRvIGNyZWF0ZSBhIHNpZ24gZG9jJyk7XG4gICAgfVxuICAgIGlmICghY29zbW9zTGlrZVRyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nvc21vc0xpa2VUcmFuc2FjdGlvbiBpcyByZXF1aXJlZCB0byBjcmVhdGUgYSBzaWduIGRvYycpO1xuICAgIH1cbiAgICBjb25zdCB0eFJhdyA9IHRoaXMuY3JlYXRlVHhSYXdGcm9tQ29zbW9zTGlrZVRyYW5zYWN0aW9uKGNvc21vc0xpa2VUcmFuc2FjdGlvbik7XG4gICAgcmV0dXJuIG1ha2VTaWduRG9jKHR4UmF3LmJvZHlCeXRlcywgdHhSYXcuYXV0aEluZm9CeXRlcywgY2hhaW5JZCwgYWNjb3VudE51bWJlcik7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgc3RyaW5nIGlzIGEgdmFsaWQgaGV4XG4gICAqIEBwYXJhbSBoZXhTdHJpbmcgLSBoZXggc3RyaW5nIGZvcm1hdFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiBzdHJpbmcgaXMgaGV4IGVsc2UgZmFsc2VcbiAgICovXG4gIGlzVmFsaWRIZXhTdHJpbmcoaGV4U3RyaW5nOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gL15bMC05QS1GYS1mXSokLy50ZXN0KGhleFN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSBXaXRoZHJhd0RlbGVnYXRvclJld2FyZHNNZXNzYWdlXG4gICAqIEBwYXJhbSB7V2l0aGRyYXdEZWxlZ2F0b3JSZXdhcmRzTWVzc2FnZX0gd2l0aGRyYXdSZXdhcmRzTWVzc2FnZSAtIFRoZSBXaXRoZHJhd0RlbGVnYXRvclJld2FyZHNNZXNzYWdlIHRvIHZhbGlkYXRlLlxuICAgKiBAdGhyb3dzIHtJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcn0gVGhyb3dzIGFuIGVycm9yIGlmIHRoZSB2YWxpZGF0b3JBZGRyZXNzIG9yIGRlbGVnYXRvckFkZHJlc3MgaXMgaW52YWxpZCBvciBtaXNzaW5nLlxuICAgKi9cbiAgdmFsaWRhdGVXaXRoZHJhd1Jld2FyZHNNZXNzYWdlKHdpdGhkcmF3UmV3YXJkc01lc3NhZ2U6IFdpdGhkcmF3RGVsZWdhdG9yUmV3YXJkc01lc3NhZ2UpIHtcbiAgICBpZiAoXG4gICAgICAhd2l0aGRyYXdSZXdhcmRzTWVzc2FnZS52YWxpZGF0b3JBZGRyZXNzIHx8XG4gICAgICAhdGhpcy5pc1ZhbGlkVmFsaWRhdG9yQWRkcmVzcyh3aXRoZHJhd1Jld2FyZHNNZXNzYWdlLnZhbGlkYXRvckFkZHJlc3MpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIFdpdGhkcmF3RGVsZWdhdG9yUmV3YXJkc01lc3NhZ2UgdmFsaWRhdG9yQWRkcmVzczogYCArIHdpdGhkcmF3UmV3YXJkc01lc3NhZ2UudmFsaWRhdG9yQWRkcmVzc1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKCF3aXRoZHJhd1Jld2FyZHNNZXNzYWdlLmRlbGVnYXRvckFkZHJlc3MgfHwgIXRoaXMuaXNWYWxpZEFkZHJlc3Mod2l0aGRyYXdSZXdhcmRzTWVzc2FnZS5kZWxlZ2F0b3JBZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKFxuICAgICAgICBgSW52YWxpZCBXaXRoZHJhd0RlbGVnYXRvclJld2FyZHNNZXNzYWdlIGRlbGVnYXRvckFkZHJlc3M6IGAgKyB3aXRoZHJhd1Jld2FyZHNNZXNzYWdlLmRlbGVnYXRvckFkZHJlc3NcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhlbHBlciBtZXRob2QgdG8gY2hlY2sgaWYgdGhlIHNwZWNpZmllZCBwcm9wZXJ0aWVzIGluIGFuIG9iamVjdCBhcmUgbWlzc2luZyBvciBudWxsLlxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIC0gVGhlIG9iamVjdCB0byBjaGVjay5cbiAgICogQHBhcmFtIHtzdHJpbmdbXX0ga2V5cyAtIEFuIGFycmF5IG9mIHByb3BlcnR5IGtleXMgdG8gY2hlY2suXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBUaHJvd3MgYW4gZXJyb3IgaWYgYW55IG9mIHRoZSBzcGVjaWZpZWQgcHJvcGVydGllcyBhcmUgbWlzc2luZyBvciBudWxsLlxuICAgKi9cbiAgaXNPYmpQcm9wZXJ0eU51bGwob2JqOiB7IFtrZXk6IHN0cmluZ106IGFueSB9LCBrZXlzOiBBcnJheTxzdHJpbmc+KSB7XG4gICAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgICAgaWYgKG9ialtrZXldID09IG51bGwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBNaXNzaW5nIG9yIG51bGwgdmFsdWUgZm9yIHByb3BlcnR5ICR7a2V5fWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgdGhlIERlbGVnYXRlT3JVbmRlbGVnZXRlTWVzc2FnZVxuICAgKiBAcGFyYW0ge0RlbGVnYXRlT3JVbmRlbGVnZXRlTWVzc2FnZX0gZGVsZWdhdGVNZXNzYWdlIC0gVGhlIERlbGVnYXRlT3JVbmRlbGVnZXRlTWVzc2FnZSB0byB2YWxpZGF0ZS5cbiAgICogQHRocm93cyB7SW52YWxpZFRyYW5zYWN0aW9uRXJyb3J9IFRocm93cyBhbiBlcnJvciBpZiB0aGUgdmFsaWRhdG9yQWRkcmVzcywgZGVsZWdhdG9yQWRkcmVzcywgb3IgYW1vdW50IGlzIGludmFsaWQgb3IgbWlzc2luZy5cbiAgICovXG4gIHZhbGlkYXRlRGVsZWdhdGVPclVuZGVsZWdhdGVNZXNzYWdlKGRlbGVnYXRlTWVzc2FnZTogRGVsZWdhdGVPclVuZGVsZWdldGVNZXNzYWdlKSB7XG4gICAgdGhpcy5pc09ialByb3BlcnR5TnVsbChkZWxlZ2F0ZU1lc3NhZ2UsIFsndmFsaWRhdG9yQWRkcmVzcycsICdkZWxlZ2F0b3JBZGRyZXNzJ10pO1xuXG4gICAgaWYgKCF0aGlzLmlzVmFsaWRWYWxpZGF0b3JBZGRyZXNzKGRlbGVnYXRlTWVzc2FnZS52YWxpZGF0b3JBZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKFxuICAgICAgICBgSW52YWxpZCBEZWxlZ2F0ZU9yVW5kZWxlZ2V0ZU1lc3NhZ2UgdmFsaWRhdG9yQWRkcmVzczogYCArIGRlbGVnYXRlTWVzc2FnZS52YWxpZGF0b3JBZGRyZXNzXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuaXNWYWxpZEFkZHJlc3MoZGVsZWdhdGVNZXNzYWdlLmRlbGVnYXRvckFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIERlbGVnYXRlT3JVbmRlbGVnZXRlTWVzc2FnZSBkZWxlZ2F0b3JBZGRyZXNzOiBgICsgZGVsZWdhdGVNZXNzYWdlLmRlbGVnYXRvckFkZHJlc3NcbiAgICAgICk7XG4gICAgfVxuICAgIHRoaXMudmFsaWRhdGVBbW91bnQoZGVsZWdhdGVNZXNzYWdlLmFtb3VudCk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSBSZWRlbGVnYXRlTWVzc2FnZVxuICAgKiBAcGFyYW0ge0RlbGVnYXRlT3JVbmRlbGVnZXRlTWVzc2FnZX0gcmVkZWxlZ2F0ZU1lc3NhZ2UgLSBUaGUgUmVkZWxlZ2F0ZU1lc3NhZ2UgdG8gdmFsaWRhdGUuXG4gICAqIEB0aHJvd3Mge0ludmFsaWRUcmFuc2FjdGlvbkVycm9yfSBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIHZhbGlkYXRvclNyY0FkZHJlc3MsIHZhbGlkYXRvckRzdEFkZHJlc3MsIGRlbGVnYXRvckFkZHJlc3MsIG9yIGFtb3VudCBpcyBpbnZhbGlkIG9yIG1pc3NpbmcuXG4gICAqL1xuICB2YWxpZGF0ZVJlZGVsZWdhdGVNZXNzYWdlKHJlZGVsZWdhdGVNZXNzYWdlOiBSZWRlbGVnYXRlTWVzc2FnZSkge1xuICAgIHRoaXMuaXNPYmpQcm9wZXJ0eU51bGwocmVkZWxlZ2F0ZU1lc3NhZ2UsIFsndmFsaWRhdG9yU3JjQWRkcmVzcycsICd2YWxpZGF0b3JEc3RBZGRyZXNzJywgJ2RlbGVnYXRvckFkZHJlc3MnXSk7XG5cbiAgICBpZiAoIXRoaXMuaXNWYWxpZFZhbGlkYXRvckFkZHJlc3MocmVkZWxlZ2F0ZU1lc3NhZ2UudmFsaWRhdG9yU3JjQWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcihcbiAgICAgICAgYEludmFsaWQgUmVkZWxlZ2F0ZU1lc3NhZ2UgdmFsaWRhdG9yU3JjQWRkcmVzczogYCArIHJlZGVsZWdhdGVNZXNzYWdlLnZhbGlkYXRvclNyY0FkZHJlc3NcbiAgICAgICk7XG4gICAgfVxuICAgIGlmICghdGhpcy5pc1ZhbGlkVmFsaWRhdG9yQWRkcmVzcyhyZWRlbGVnYXRlTWVzc2FnZS52YWxpZGF0b3JEc3RBZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKFxuICAgICAgICBgSW52YWxpZCBSZWRlbGVnYXRlTWVzc2FnZSB2YWxpZGF0b3JEc3RBZGRyZXNzOiBgICsgcmVkZWxlZ2F0ZU1lc3NhZ2UudmFsaWRhdG9yRHN0QWRkcmVzc1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLmlzVmFsaWRBZGRyZXNzKHJlZGVsZWdhdGVNZXNzYWdlLmRlbGVnYXRvckFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIERlbGVnYXRlT3JVbmRlbGVnZXRlTWVzc2FnZSBkZWxlZ2F0b3JBZGRyZXNzOiBgICsgcmVkZWxlZ2F0ZU1lc3NhZ2UuZGVsZWdhdG9yQWRkcmVzc1xuICAgICAgKTtcbiAgICB9XG4gICAgdGhpcy52YWxpZGF0ZUFtb3VudChyZWRlbGVnYXRlTWVzc2FnZS5hbW91bnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyB0aGUgQ3VzdG9tTWVzc2FnZVxuICAgKiBAcGFyYW0ge0N1c3RvbU1lc3NhZ2V9IGN1c3RvbU1lc3NhZ2UgLSBUaGUgQ3VzdG9tTWVzc2FnZSB0byB2YWxpZGF0ZS5cbiAgICogQHRocm93cyB7SW52YWxpZFRyYW5zYWN0aW9uRXJyb3J9IFRocm93cyBhbiBlcnJvciBpZiB0aGUgY3VzdG9tIG1lc3NhZ2UgaXMgaW52YWxpZCBvciBtaXNzaW5nIHJlcXVpcmVkIGZpZWxkcy5cbiAgICogQHRocm93cyB7Tm90U3VwcG9ydGVkfSBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIGN1c3RvbSBtZXNzYWdlIGRhdGEgaXMgbm90IHN1cHBvcnRlZC5cbiAgICovXG4gIHZhbGlkYXRlQ3VzdG9tTWVzc2FnZShjdXN0b21NZXNzYWdlOiBDdXN0b21NZXNzYWdlKSB7XG4gICAgdGhyb3cgbmV3IE5vdFN1cHBvcnRlZCgnQ3VzdG9tIG1lc3NhZ2UgZGF0YSBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSBNZXNzYWdlRGF0YVxuICAgKiBAcGFyYW0ge01lc3NhZ2VEYXRhfSBtZXNzYWdlRGF0YSAtIFRoZSBNZXNzYWdlRGF0YSB0byB2YWxpZGF0ZS5cbiAgICogQHRocm93cyB7SW52YWxpZFRyYW5zYWN0aW9uRXJyb3J9IFRocm93cyBhbiBlcnJvciBpZiB0aGUgbWVzc2FnZURhdGEgaXMgaW52YWxpZCBvciBtaXNzaW5nIHJlcXVpcmVkIGZpZWxkcy5cbiAgICovXG4gIHZhbGlkYXRlTWVzc2FnZURhdGEobWVzc2FnZURhdGE6IE1lc3NhZ2VEYXRhPEN1c3RvbU1lc3NhZ2U+KTogdm9pZCB7XG4gICAgaWYgKG1lc3NhZ2VEYXRhID09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBNZXNzYWdlRGF0YTogdW5kZWZpbmVkYCk7XG4gICAgfVxuICAgIGlmIChtZXNzYWdlRGF0YS50eXBlVXJsID09IG51bGwgfHwgdGhpcy5nZXRUcmFuc2FjdGlvblR5cGVGcm9tVHlwZVVybChtZXNzYWdlRGF0YS50eXBlVXJsKSA9PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgTWVzc2FnZURhdGEgdHlwZXVybDogYCArIG1lc3NhZ2VEYXRhLnR5cGVVcmwpO1xuICAgIH1cblxuICAgIGNvbnN0IHR5cGUgPSB0aGlzLmdldFRyYW5zYWN0aW9uVHlwZUZyb21UeXBlVXJsKG1lc3NhZ2VEYXRhLnR5cGVVcmwpO1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZDoge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IG1lc3NhZ2VEYXRhLnZhbHVlIGFzIFNlbmRNZXNzYWdlO1xuICAgICAgICB0aGlzLnZhbGlkYXRlU2VuZE1lc3NhZ2UodmFsdWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBY3RpdmF0ZTpcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdEZWFjdGl2YXRlOiB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gbWVzc2FnZURhdGEudmFsdWUgYXMgRGVsZWdhdGVPclVuZGVsZWdldGVNZXNzYWdlO1xuICAgICAgICB0aGlzLnZhbGlkYXRlRGVsZWdhdGVPclVuZGVsZWdhdGVNZXNzYWdlKHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nV2l0aGRyYXc6IHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBtZXNzYWdlRGF0YS52YWx1ZSBhcyBXaXRoZHJhd0RlbGVnYXRvclJld2FyZHNNZXNzYWdlO1xuICAgICAgICB0aGlzLnZhbGlkYXRlV2l0aGRyYXdSZXdhcmRzTWVzc2FnZSh2YWx1ZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsOiB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gbWVzc2FnZURhdGEudmFsdWUgYXMgRXhlY3V0ZUNvbnRyYWN0TWVzc2FnZTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZUV4ZWN1dGVDb250cmFjdE1lc3NhZ2UodmFsdWUsIFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGwpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdSZWRlbGVnYXRlOiB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gbWVzc2FnZURhdGEudmFsdWUgYXMgUmVkZWxlZ2F0ZU1lc3NhZ2U7XG4gICAgICAgIHRoaXMudmFsaWRhdGVSZWRlbGVnYXRlTWVzc2FnZSh2YWx1ZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQ3VzdG9tVHg6IHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBtZXNzYWdlRGF0YS52YWx1ZSBhcyBDdXN0b21NZXNzYWdlO1xuICAgICAgICB0aGlzLnZhbGlkYXRlQ3VzdG9tTWVzc2FnZSh2YWx1ZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIE1lc3NhZ2VEYXRhIFR5cGVVcmwgaXMgbm90IHN1cHBvcnRlZDogYCArIG1lc3NhZ2VEYXRhLnR5cGVVcmwpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgdGhlIENvc21vcy1saWtlIHRyYW5zYWN0aW9uLlxuICAgKiBAcGFyYW0ge0Nvc21vc0xpa2VUcmFuc2FjdGlvbn0gdHggLSBUaGUgdHJhbnNhY3Rpb24gdG8gdmFsaWRhdGUuXG4gICAqIEB0aHJvd3Mge0ludmFsaWRUcmFuc2FjdGlvbkVycm9yfSBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIHRyYW5zYWN0aW9uIGlzIGludmFsaWQgb3IgbWlzc2luZyByZXF1aXJlZCBmaWVsZHMuXG4gICAqL1xuICB2YWxpZGF0ZVRyYW5zYWN0aW9uKHR4OiBDb3Ntb3NMaWtlVHJhbnNhY3Rpb248Q3VzdG9tTWVzc2FnZT4pOiB2b2lkIHtcbiAgICB0aGlzLnZhbGlkYXRlU2VxdWVuY2UodHguc2VxdWVuY2UpO1xuICAgIHRoaXMudmFsaWRhdGVHYXNCdWRnZXQodHguZ2FzQnVkZ2V0KTtcbiAgICB0aGlzLnZhbGlkYXRlUHVibGljS2V5KHR4LnB1YmxpY0tleSk7XG4gICAgaWYgKHR4LnNlbmRNZXNzYWdlcyA9PT0gdW5kZWZpbmVkIHx8IHR4LnNlbmRNZXNzYWdlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbjogbWVzc2FnZXMgaXMgcmVxdWlyZWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdHguc2VuZE1lc3NhZ2VzLmZvckVhY2goKG1lc3NhZ2UpID0+IHRoaXMudmFsaWRhdGVNZXNzYWdlRGF0YShtZXNzYWdlKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBDb3Ntb3MtbGlrZSB0cmFuc2FjdGlvbi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHNlcXVlbmNlIC0gVGhlIHNlbmRlciBhZGRyZXNzIHNlcXVlbmNlIG51bWJlciBmb3IgdGhlIHRyYW5zYWN0aW9uLlxuICAgKiBAcGFyYW0ge01lc3NhZ2VEYXRhW119IG1lc3NhZ2VzIC0gVGhlIGFycmF5IG9mIG1lc3NhZ2UgZGF0YSBmb3IgdGhlIHRyYW5zYWN0aW9uLlxuICAgKiBAcGFyYW0ge0ZlZURhdGF9IGdhc0J1ZGdldCAtIFRoZSBmZWUgZGF0YSBmb3IgdGhlIHRyYW5zYWN0aW9uLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3B1YmxpY0tleV0gLSBUaGUgcHVibGljIGtleSBhc3NvY2lhdGVkIHdpdGggdGhlIHNlbmRlci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFttZW1vXSAtIFRoZSBtZW1vIGZvciB0aGUgdHJhbnNhY3Rpb24uXG4gICAqIEByZXR1cm5zIHtDb3Ntb3NMaWtlVHJhbnNhY3Rpb259IFJldHVybnMgdGhlIGNyZWF0ZWQgQ29zbW9zLWxpa2UgdHJhbnNhY3Rpb24uXG4gICAqIEB0aHJvd3Mge0ludmFsaWRUcmFuc2FjdGlvbkVycm9yfSBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIGNyZWF0ZWQgdHJhbnNhY3Rpb24gaXMgaW52YWxpZC5cbiAgICovXG4gIGNyZWF0ZVRyYW5zYWN0aW9uKFxuICAgIHNlcXVlbmNlOiBudW1iZXIsXG4gICAgbWVzc2FnZXM6IE1lc3NhZ2VEYXRhPEN1c3RvbU1lc3NhZ2U+W10sXG4gICAgZ2FzQnVkZ2V0OiBGZWVEYXRhLFxuICAgIHB1YmxpY0tleT86IHN0cmluZyxcbiAgICBtZW1vPzogc3RyaW5nXG4gICk6IENvc21vc0xpa2VUcmFuc2FjdGlvbjxDdXN0b21NZXNzYWdlPiB7XG4gICAgY29uc3QgY29zbW9zTGlrZVR4biA9IHtcbiAgICAgIHNlcXVlbmNlOiBzZXF1ZW5jZSxcbiAgICAgIHNlbmRNZXNzYWdlczogbWVzc2FnZXMsXG4gICAgICBnYXNCdWRnZXQ6IGdhc0J1ZGdldCxcbiAgICAgIHB1YmxpY0tleTogcHVibGljS2V5LFxuICAgICAgbWVtbzogbWVtbyxcbiAgICB9O1xuICAgIHRoaXMudmFsaWRhdGVUcmFuc2FjdGlvbihjb3Ntb3NMaWtlVHhuKTtcbiAgICByZXR1cm4gY29zbW9zTGlrZVR4bjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgQ29zbW9zLWxpa2UgdHJhbnNhY3Rpb24gd2l0aCBhIGhhc2guXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzZXF1ZW5jZSAtIFRoZSBzZW5kZXIgYWRkcmVzcyBzZXF1ZW5jZSBudW1iZXIgZm9yIHRoZSB0cmFuc2FjdGlvbi5cbiAgICogQHBhcmFtIHtNZXNzYWdlRGF0YVtdfSBtZXNzYWdlcyAtIFRoZSBhcnJheSBvZiBtZXNzYWdlIGRhdGEgZm9yIHRoZSB0cmFuc2FjdGlvbi5cbiAgICogQHBhcmFtIHtGZWVEYXRhfSBnYXNCdWRnZXQgLSBUaGUgZmVlIGRhdGEgZm9yIHRoZSB0cmFuc2FjdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwdWJsaWNLZXldIC0gVGhlIHB1YmxpYyBrZXkgYXNzb2NpYXRlZCB3aXRoIHRoZSB0cmFuc2FjdGlvbi5cbiAgICogQHBhcmFtIHtCdWZmZXJ9IFtzaWduYXR1cmVdIC0gVGhlIHNpZ25hdHVyZSBmb3IgdGhlIHRyYW5zYWN0aW9uLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW21lbW9dIC0gVGhlIG1lbW8gZm9yIHRoZSB0cmFuc2FjdGlvbi5cbiAgICogQHJldHVybnMge0Nvc21vc0xpa2VUcmFuc2FjdGlvbn0gUmV0dXJucyB0aGUgY3JlYXRlZCBDb3Ntb3MtbGlrZSB0cmFuc2FjdGlvbiB3aXRoIHRoZSBoYXNoIGFuZCBzaWduYXR1cmUgaWYgcHJvdmlkZWQuXG4gICAqL1xuICBjcmVhdGVUcmFuc2FjdGlvbldpdGhIYXNoKFxuICAgIHNlcXVlbmNlOiBudW1iZXIsXG4gICAgbWVzc2FnZXM6IE1lc3NhZ2VEYXRhPEN1c3RvbU1lc3NhZ2U+W10sXG4gICAgZ2FzQnVkZ2V0OiBGZWVEYXRhLFxuICAgIHB1YmxpY0tleT86IHN0cmluZyxcbiAgICBzaWduYXR1cmU/OiBCdWZmZXIsXG4gICAgbWVtbz86IHN0cmluZ1xuICApOiBDb3Ntb3NMaWtlVHJhbnNhY3Rpb248Q3VzdG9tTWVzc2FnZT4ge1xuICAgIGNvbnN0IGNvc21vc0xpa2VUeG4gPSB0aGlzLmNyZWF0ZVRyYW5zYWN0aW9uKHNlcXVlbmNlLCBtZXNzYWdlcywgZ2FzQnVkZ2V0LCBwdWJsaWNLZXksIG1lbW8pO1xuICAgIGxldCBoYXNoID0gY29uc3RhbnRzLlVOQVZBSUxBQkxFX1RFWFQ7XG4gICAgaWYgKHNpZ25hdHVyZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCB1bnNpZ25lZFR4ID0gdGhpcy5jcmVhdGVUeFJhd0Zyb21Db3Ntb3NMaWtlVHJhbnNhY3Rpb24oY29zbW9zTGlrZVR4bik7XG4gICAgICBjb25zdCBzaWduZWRUeCA9IFR4UmF3LmZyb21QYXJ0aWFsKHtcbiAgICAgICAgYm9keUJ5dGVzOiB1bnNpZ25lZFR4LmJvZHlCeXRlcyxcbiAgICAgICAgYXV0aEluZm9CeXRlczogdW5zaWduZWRUeC5hdXRoSW5mb0J5dGVzLFxuICAgICAgICBzaWduYXR1cmVzOiBbc2lnbmF0dXJlXSxcbiAgICAgIH0pO1xuICAgICAgaGFzaCA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpXG4gICAgICAgIC51cGRhdGUoVHhSYXcuZW5jb2RlKHNpZ25lZFR4KS5maW5pc2goKSlcbiAgICAgICAgLmRpZ2VzdCgpXG4gICAgICAgIC50b1N0cmluZygnaGV4JylcbiAgICAgICAgLnRvTG9jYWxlVXBwZXJDYXNlKCdlbi1VUycpO1xuICAgICAgcmV0dXJuIHsgLi4uY29zbW9zTGlrZVR4biwgaGFzaDogaGFzaCwgc2lnbmF0dXJlOiBzaWduYXR1cmUgfTtcbiAgICB9XG4gICAgcmV0dXJuIHsgLi4uY29zbW9zTGlrZVR4biwgaGFzaDogaGFzaCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIERlc2VyaWFsaXplcyBiYXNlNjQgZW5vY2RlZCByYXcgdHJhbnNhY3Rpb24gc3RyaW5nIGludG8gQHNlZSBDb3Ntb3NMaWtlVHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IHJhd1R4IGJhc2U2NCBlbm9jZGVkIHJhdyB0cmFuc2FjdGlvbiBzdHJpbmdcbiAgICogQHJldHVybnMge0Nvc21vc0xpa2VUcmFuc2FjdGlvbn0gRGVzZXJpYWxpemVkIGNvc21vc0xpa2VUcmFuc2FjdGlvblxuICAgKi9cbiAgZGVzZXJpYWxpemVUcmFuc2FjdGlvbihyYXdUeDogc3RyaW5nKTogQ29zbW9zTGlrZVRyYW5zYWN0aW9uPEN1c3RvbU1lc3NhZ2U+IHtcbiAgICBjb25zdCBkZWNvZGVkVHggPSB0aGlzLmdldERlY29kZWRUeEZyb21SYXdCYXNlNjQocmF3VHgpO1xuICAgIGNvbnN0IHR5cGVVcmwgPSB0aGlzLmdldFR5cGVVcmxGcm9tRGVjb2RlZFR4KGRlY29kZWRUeCk7XG4gICAgY29uc3QgdHlwZTogVHJhbnNhY3Rpb25UeXBlIHwgdW5kZWZpbmVkID0gdGhpcy5nZXRUcmFuc2FjdGlvblR5cGVGcm9tVHlwZVVybCh0eXBlVXJsKTtcbiAgICBsZXQgc2VuZE1lc3NhZ2VEYXRhOiBNZXNzYWdlRGF0YTxDdXN0b21NZXNzYWdlPltdO1xuICAgIGlmICh0eXBlID09PSBUcmFuc2FjdGlvblR5cGUuU2VuZCkge1xuICAgICAgc2VuZE1lc3NhZ2VEYXRhID0gdGhpcy5nZXRTZW5kTWVzc2FnZURhdGFGcm9tRGVjb2RlZFR4KGRlY29kZWRUeCk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0FjdGl2YXRlIHx8IHR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nRGVhY3RpdmF0ZSkge1xuICAgICAgc2VuZE1lc3NhZ2VEYXRhID0gdGhpcy5nZXREZWxlZ2F0ZU9yVW5kZWxlZ2F0ZU1lc3NhZ2VEYXRhRnJvbURlY29kZWRUeChkZWNvZGVkVHgpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdXaXRoZHJhdykge1xuICAgICAgc2VuZE1lc3NhZ2VEYXRhID0gdGhpcy5nZXRXaXRoZHJhd1Jld2FyZHNNZXNzYWdlRGF0YUZyb21EZWNvZGVkVHgoZGVjb2RlZFR4KTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGwpIHtcbiAgICAgIHNlbmRNZXNzYWdlRGF0YSA9IHRoaXMuZ2V0RXhlY3V0ZUNvbnRyYWN0TWVzc2FnZURhdGFGcm9tRGVjb2RlZFR4KGRlY29kZWRUeCk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ1JlZGVsZWdhdGUpIHtcbiAgICAgIHNlbmRNZXNzYWdlRGF0YSA9IHRoaXMuZ2V0UmVkZWxlZ2F0ZU1lc3NhZ2VEYXRhRnJvbURlY29kZWRUeChkZWNvZGVkVHgpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLkN1c3RvbVR4KSB7XG4gICAgICBzZW5kTWVzc2FnZURhdGEgPSB0aGlzLmdldEN1c3RvbU1lc3NhZ2VEYXRhRnJvbURlY29kZWRUeChkZWNvZGVkVHgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RyYW5zYWN0aW9uIHR5cGUgbm90IHN1cHBvcnRlZDogJyArIHR5cGVVcmwpO1xuICAgIH1cbiAgICBjb25zdCBzZXF1ZW5jZSA9IHRoaXMuZ2V0U2VxdWVuY2VGcm9tRGVjb2RlZFR4KGRlY29kZWRUeCk7XG4gICAgY29uc3QgZ2FzQnVkZ2V0ID0gdGhpcy5nZXRHYXNCdWRnZXRGcm9tRGVjb2RlZFR4KGRlY29kZWRUeCk7XG4gICAgY29uc3QgcHVibGljS2V5ID0gdGhpcy5nZXRQdWJsaWNLZXlGcm9tRGVjb2RlZFR4KGRlY29kZWRUeCk7XG4gICAgY29uc3Qgc2lnbmF0dXJlID0gZGVjb2RlZFR4LnNpZ25hdHVyZXM/LlswXSAhPT0gdW5kZWZpbmVkID8gQnVmZmVyLmZyb20oZGVjb2RlZFR4LnNpZ25hdHVyZXNbMF0pIDogdW5kZWZpbmVkO1xuICAgIHJldHVybiB0aGlzLmNyZWF0ZVRyYW5zYWN0aW9uV2l0aEhhc2goXG4gICAgICBzZXF1ZW5jZSxcbiAgICAgIHNlbmRNZXNzYWdlRGF0YSxcbiAgICAgIGdhc0J1ZGdldCxcbiAgICAgIHB1YmxpY0tleSxcbiAgICAgIHNpZ25hdHVyZSxcbiAgICAgIGRlY29kZWRUeC5ib2R5Py5tZW1vXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgYW4gYXJyYXkgb2YgY29pbiBhbW91bnRzLlxuICAgKiBAcGFyYW0ge0NvaW5bXX0gYW1vdW50QXJyYXkgLSBUaGUgYXJyYXkgb2YgY29pbiBhbW91bnRzIHRvIHZhbGlkYXRlLlxuICAgKiBAcGFyYW0ge1RyYW5zYWN0aW9uVHlwZX0gdHJhbnNhY3Rpb25UeXBlIC0gb3B0aW9uYWwgZmllbGQgZm9yIHRyYW5zYWN0aW9uIHR5cGVcbiAgICovXG4gIHZhbGlkYXRlQW1vdW50RGF0YShhbW91bnRBcnJheTogQ29pbltdLCB0cmFuc2FjdGlvblR5cGU/OiBUcmFuc2FjdGlvblR5cGUpOiB2b2lkIHtcbiAgICBhbW91bnRBcnJheS5mb3JFYWNoKChjb2luQW1vdW50KSA9PiB7XG4gICAgICB0aGlzLnZhbGlkYXRlQW1vdW50KGNvaW5BbW91bnQsIHRyYW5zYWN0aW9uVHlwZSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSBnYXMgbGltaXQgYW5kIGdhcyBhbW91bnQgZm9yIGEgdHJhbnNhY3Rpb24uXG4gICAqIEBwYXJhbSB7RmVlRGF0YX0gZ2FzQnVkZ2V0IC0gVGhlIGdhcyBidWRnZXQgdG8gdmFsaWRhdGUuXG4gICAqIEB0aHJvd3Mge0ludmFsaWRUcmFuc2FjdGlvbkVycm9yfSBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIGdhcyBidWRnZXQgaXMgaW52YWxpZC5cbiAgICovXG4gIHZhbGlkYXRlR2FzQnVkZ2V0KGdhc0J1ZGdldDogRmVlRGF0YSk6IHZvaWQge1xuICAgIGlmIChnYXNCdWRnZXQuZ2FzTGltaXQgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGdhcyBsaW1pdCAnICsgZ2FzQnVkZ2V0Lmdhc0xpbWl0KTtcbiAgICB9XG4gICAgdGhpcy52YWxpZGF0ZUFtb3VudERhdGEoZ2FzQnVkZ2V0LmFtb3VudCk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIGEgc2VuZCBtZXNzYWdlIGZvciBhIHRyYW5zYWN0aW9uLlxuICAgKiBAcGFyYW0ge1NlbmRNZXNzYWdlfSBzZW5kTWVzc2FnZSAtIFRoZSBzZW5kIG1lc3NhZ2UgdG8gdmFsaWRhdGUuXG4gICAqIEB0aHJvd3Mge0ludmFsaWRUcmFuc2FjdGlvbkVycm9yfSBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIHNlbmQgbWVzc2FnZSBpcyBpbnZhbGlkLlxuICAgKi9cbiAgdmFsaWRhdGVTZW5kTWVzc2FnZShzZW5kTWVzc2FnZTogU2VuZE1lc3NhZ2UpIHtcbiAgICBpZiAoIXNlbmRNZXNzYWdlLnRvQWRkcmVzcyB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhzZW5kTWVzc2FnZS50b0FkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgU2VuZE1lc3NhZ2UgdG9BZGRyZXNzOiBgICsgc2VuZE1lc3NhZ2UudG9BZGRyZXNzKTtcbiAgICB9XG4gICAgaWYgKCFzZW5kTWVzc2FnZS5mcm9tQWRkcmVzcyB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhzZW5kTWVzc2FnZS5mcm9tQWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBTZW5kTWVzc2FnZSBmcm9tQWRkcmVzczogYCArIHNlbmRNZXNzYWdlLmZyb21BZGRyZXNzKTtcbiAgICB9XG4gICAgdGhpcy52YWxpZGF0ZUFtb3VudERhdGEoc2VuZE1lc3NhZ2UuYW1vdW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgYSBjb2luIGFtb3VudC5cbiAgICogQHBhcmFtIHtDb2lufSBhbW91bnQgLSBUaGUgY29pbiBhbW91bnQgdG8gdmFsaWRhdGUuXG4gICAqIEBwYXJhbSB7VHJhbnNhY3Rpb25UeXBlfSB0cmFuc2FjdGlvblR5cGUgLSBvcHRpb25hbCBmaWVsZCBmb3IgdHJhbnNhY3Rpb24gdHlwZVxuICAgKiBAdGhyb3dzIHtJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcn0gVGhyb3dzIGFuIGVycm9yIGlmIHRoZSBjb2luIGFtb3VudCBpcyBpbnZhbGlkLlxuICAgKi9cbiAgdmFsaWRhdGVBbW91bnQoYW1vdW50OiBDb2luLCB0cmFuc2FjdGlvblR5cGU/OiBUcmFuc2FjdGlvblR5cGUpOiB2b2lkIHtcbiAgICB0aHJvdyBuZXcgTm90SW1wbGVtZW50ZWRFcnJvcigndmFsaWRhdGVBbW91bnQgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgY29zbW9zIGxpa2UgQmVjaDMyIGFkZHJlc3MgbWF0Y2hlcyBnaXZlbiByZWd1bGFyIGV4cHJlc3Npb24gYW5kXG4gICAqIHZhbGlkYXRlcyBtZW1vSWQgaWYgcHJlc2VudFxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzc1xuICAgKiBAcGFyYW0ge1JlZ0V4cH0gcmVnRXhwIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byB2YWxpZGF0ZSB0aGUgcm9vdCBhZGRyZXNzIGFnYWluc3QgYWZ0ZXIgdHJpbW1pbmcgdGhlIG1lbW9JZFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiBhZGRyZXNzIGlzIHZhbGlkXG4gICAqL1xuICBwcm90ZWN0ZWQgaXNWYWxpZENvc21vc0xpa2VBZGRyZXNzV2l0aE1lbW9JZChhZGRyZXNzOiBzdHJpbmcsIHJlZ0V4cDogUmVnRXhwKTogYm9vbGVhbiB7XG4gICAgaWYgKHR5cGVvZiBhZGRyZXNzICE9PSAnc3RyaW5nJykgcmV0dXJuIGZhbHNlO1xuICAgIGNvbnN0IGFkZHJlc3NBcnJheSA9IGFkZHJlc3Muc3BsaXQoJz9tZW1vSWQ9Jyk7XG4gICAgaWYgKFxuICAgICAgIVsxLCAyXS5pbmNsdWRlcyhhZGRyZXNzQXJyYXkubGVuZ3RoKSB8fCAvLyBzaG91bGQgaGF2ZSBhdCBtb3N0IG9uZSBvY2N1cnJlbmNlIG9mICdtZW1vSWQ9J1xuICAgICAgIXRoaXMuaXNWYWxpZEJlY2gzMkFkZHJlc3NNYXRjaGluZ1JlZ2V4KGFkZHJlc3NBcnJheVswXSwgcmVnRXhwKSB8fFxuICAgICAgKGFkZHJlc3NBcnJheVsxXSAmJiAhdGhpcy5pc1ZhbGlkTWVtb0lkKGFkZHJlc3NBcnJheVsxXSkpXG4gICAgKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBhZGRyZXNzIGlzIHZhbGlkIEJlY2gzMiBhbmQgbWF0Y2hlcyBnaXZlbiByZWd1bGFyIGV4cHJlc3Npb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3NcbiAgICogQHBhcmFtIHtSZWdFeHB9IHJlZ0V4cCBSZWd1bGFyIGV4cHJlc3Npb24gdG8gdmFsaWRhdGUgdGhlIGFkZHJlc3MgYWdhaW5zdFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiBhZGRyZXNzIGlzIHZhbGlkXG4gICAqL1xuICBwcm90ZWN0ZWQgaXNWYWxpZEJlY2gzMkFkZHJlc3NNYXRjaGluZ1JlZ2V4KGFkZHJlc3M6IHN0cmluZywgcmVnRXhwOiBSZWdFeHApOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgZnJvbUJlY2gzMihhZGRyZXNzKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiByZWdFeHAudGVzdChhZGRyZXNzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgYSBtZW1vIGlkIGlzIHZhbGlkXG4gICAqXG4gICAqIEBwYXJhbSBtZW1vSWQgbWVtbyBpZFxuICAgKiBAcmV0dXJucyB0cnVlIGlmIG1lbW8gaWQgaXMgdmFsaWRcbiAgICovXG4gIGlzVmFsaWRNZW1vSWQobWVtb0lkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAvLyBBbGxvdyBhbHBoYW51bWVyaWMgbWVtbyBJRHMgKGluY2x1ZGluZyB1cHBlcmNhc2UgYW5kIGxvd2VyY2FzZSBsZXR0ZXJzKVxuICAgIGNvbnN0IGFscGhhbnVtZXJpY1JlZ2V4ID0gL15bMC05YS16QS1aXSskLztcblxuICAgIC8vIENoZWNrIGlmIHRoZSBtZW1vSWQgaXMgYWxwaGFudW1lcmljXG4gICAgaWYgKCFhbHBoYW51bWVyaWNSZWdleC50ZXN0KG1lbW9JZCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBJZiB0aGUgbWVtb0lkIGlzIHB1cmVseSBudW1lcmljLCBlbnN1cmUgaXQgaXMgYSBwb3NpdGl2ZSBpbnRlZ2VyXG4gICAgaWYgKC9eXFxkKyQvLnRlc3QobWVtb0lkKSkge1xuICAgICAgY29uc3QgbWVtb0lkTnVtYmVyID0gbmV3IEJpZ051bWJlcihtZW1vSWQpO1xuICAgICAgcmV0dXJuIG1lbW9JZE51bWJlci5ndGUoMCkgJiYgbWVtb0lkTnVtYmVyLmlzSW50ZWdlcigpO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBpZiB0aGUgYWRkcmVzcyBtYXRjaGVzIHdpdGggcmVnZXggQHNlZSBhY2NvdW50QWRkcmVzc1JlZ2V4XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzXG4gICAqIEByZXR1cm5zIHtib29sZWFufSAtIHRoZSB2YWxpZGF0aW9uIHJlc3VsdFxuICAgKi9cbiAgaXNWYWxpZFZhbGlkYXRvckFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ2lzVmFsaWRWYWxpZGF0b3JBZGRyZXNzIG5vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBpZiB0aGUgYWRkcmVzcyBtYXRjaGVzIHdpdGggcmVnZXggQHNlZSBhY2NvdW50QWRkcmVzc1JlZ2V4XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzXG4gICAqIEByZXR1cm5zIHtib29sZWFufSAtIHRoZSB2YWxpZGF0aW9uIHJlc3VsdFxuICAgKi9cbiAgaXNWYWxpZEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ2lzVmFsaWRBZGRyZXNzIG5vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBpZiB0aGUgYWRkcmVzcyBtYXRjaGVzIHdpdGggcmVnZXggQHNlZSBjb250cmFjdEFkZHJlc3NSZWdleFxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzc1xuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0aGUgdmFsaWRhdGlvbiByZXN1bHRcbiAgICovXG4gIGlzVmFsaWRDb250cmFjdEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ2lzVmFsaWRDb250cmFjdEFkZHJlc3Mgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIGEgZXhlY3V0ZSBjb250cmFjdCBtZXNzYWdlXG4gICAqIEBwYXJhbSB7RXhlY3V0ZUNvbnRyYWN0TWVzc2FnZX0gbWVzc2FnZSAtIFRoZSBleGVjdXRlIGNvbnRyYWN0IG1lc3NhZ2UgdG8gdmFsaWRhdGVcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvblR5cGV9IHRyYW5zYWN0aW9uVHlwZSAtIG9wdGlvbmFsIGZpZWxkIGZvciB0cmFuc2FjdGlvbiB0eXBlXG4gICAqIEB0aHJvd3Mge0ludmFsaWRUcmFuc2FjdGlvbkVycm9yfSBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIG1lc3NhZ2UgaXMgaW52YWxpZFxuICAgKi9cbiAgdmFsaWRhdGVFeGVjdXRlQ29udHJhY3RNZXNzYWdlKG1lc3NhZ2U6IEV4ZWN1dGVDb250cmFjdE1lc3NhZ2UsIHRyYW5zYWN0aW9uVHlwZT86IFRyYW5zYWN0aW9uVHlwZSkge1xuICAgIGlmICghbWVzc2FnZS5jb250cmFjdCB8fCAhdGhpcy5pc1ZhbGlkQ29udHJhY3RBZGRyZXNzKG1lc3NhZ2UuY29udHJhY3QpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgRXhlY3V0ZUNvbnRyYWN0TWVzc2FnZSBjb250cmFjdCBhZGRyZXNzOiBgICsgbWVzc2FnZS5jb250cmFjdCk7XG4gICAgfVxuICAgIGlmICghbWVzc2FnZS5zZW5kZXIgfHwgIXRoaXMuaXNWYWxpZEFkZHJlc3MobWVzc2FnZS5zZW5kZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgRXhlY3V0ZUNvbnRyYWN0TWVzc2FnZSBzZW5kZXIgYWRkcmVzczogYCArIG1lc3NhZ2Uuc2VuZGVyKTtcbiAgICB9XG4gICAgaWYgKCFtZXNzYWdlLm1zZykge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIEV4ZWN1dGVDb250cmFjdE1lc3NhZ2UgbXNnOiBgICsgbWVzc2FnZS5tc2cpO1xuICAgIH1cbiAgICBpZiAobWVzc2FnZS5mdW5kcykge1xuICAgICAgdGhpcy52YWxpZGF0ZUFtb3VudERhdGEobWVzc2FnZS5mdW5kcywgdHJhbnNhY3Rpb25UeXBlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IGNvaW4gc3BlY2lmaWMgaGFzaCBmdW5jdGlvblxuICAgKiBAcmV0dXJucyB7SGFzaH0gVGhlIGhhc2ggZnVuY3Rpb25cbiAgICovXG4gIGdldEhhc2hGdW5jdGlvbigpOiBIYXNoIHtcbiAgICByZXR1cm4gY3JlYXRlSGFzaCgnc2hhMjU2Jyk7XG4gIH1cblxuICBnZXRUb2tlbkRlbm9tc1VzaW5nQ29pbkZhbWlseShjb2luRmFtaWx5OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgLy8gdXNpbmcgc2V0IHRvIHJlbW92ZSBkdXBsaWNhdGVzIGFzIGRlbm9tIGNhbiBiZSBzYW1lIG9uIHRlc3RuZXQgYW5kIG1haW5uZXQgZm9yIGEgZmV3IHRva2Vuc1xuICAgIHJldHVybiBbXG4gICAgICAuLi5uZXcgU2V0KFxuICAgICAgICBjb2luc1xuICAgICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgICAoY29pbikgPT4gY29pbi5mYW1pbHkudG9Mb3dlckNhc2UoKSA9PT0gY29pbkZhbWlseS50b0xvd2VyQ2FzZSgpICYmIGNvaW4uaXNUb2tlbiAmJiBjb2luLmRlbm9tICE9PSB1bmRlZmluZWRcbiAgICAgICAgICApXG4gICAgICAgICAgLm1hcCgoY29pbikgPT4gY29pbi5kZW5vbSBhcyBzdHJpbmcpXG4gICAgICApLFxuICAgIF07XG4gIH1cbn1cblxuY29uc3QgdXRpbHMgPSBuZXcgQ29zbW9zVXRpbHMoKTtcblxuZXhwb3J0IGRlZmF1bHQgdXRpbHM7XG4iXX0=
|