@bitgo-beta/sdk-coin-xtz 1.4.3-alpha.398 → 1.4.3-alpha.399

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.
Files changed (41) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +8 -8
  3. package/dist/src/index.d.ts +0 -5
  4. package/dist/src/index.d.ts.map +0 -1
  5. package/dist/src/index.js +0 -44
  6. package/dist/src/lib/address.d.ts +0 -8
  7. package/dist/src/lib/address.d.ts.map +0 -1
  8. package/dist/src/lib/address.js +0 -10
  9. package/dist/src/lib/iface.d.ts +0 -148
  10. package/dist/src/lib/iface.d.ts.map +0 -1
  11. package/dist/src/lib/iface.js +0 -3
  12. package/dist/src/lib/index.d.ts +0 -10
  13. package/dist/src/lib/index.d.ts.map +0 -1
  14. package/dist/src/lib/index.js +0 -51
  15. package/dist/src/lib/keyPair.d.ts +0 -40
  16. package/dist/src/lib/keyPair.d.ts.map +0 -1
  17. package/dist/src/lib/keyPair.js +0 -149
  18. package/dist/src/lib/multisigUtils.d.ts +0 -134
  19. package/dist/src/lib/multisigUtils.d.ts.map +0 -1
  20. package/dist/src/lib/multisigUtils.js +0 -1193
  21. package/dist/src/lib/transaction.d.ts +0 -119
  22. package/dist/src/lib/transaction.d.ts.map +0 -1
  23. package/dist/src/lib/transaction.js +0 -329
  24. package/dist/src/lib/transactionBuilder.d.ts +0 -171
  25. package/dist/src/lib/transactionBuilder.d.ts.map +0 -1
  26. package/dist/src/lib/transactionBuilder.js +0 -453
  27. package/dist/src/lib/transferBuilder.d.ts +0 -24
  28. package/dist/src/lib/transferBuilder.d.ts.map +0 -1
  29. package/dist/src/lib/transferBuilder.js +0 -64
  30. package/dist/src/lib/utils.d.ts +0 -280
  31. package/dist/src/lib/utils.d.ts.map +0 -1
  32. package/dist/src/lib/utils.js +0 -492
  33. package/dist/src/register.d.ts +0 -3
  34. package/dist/src/register.d.ts.map +0 -1
  35. package/dist/src/register.js +0 -11
  36. package/dist/src/txtz.d.ts +0 -13
  37. package/dist/src/txtz.d.ts.map +0 -1
  38. package/dist/src/txtz.js +0 -14
  39. package/dist/src/xtz.d.ts +0 -125
  40. package/dist/src/xtz.d.ts.map +0 -1
  41. package/dist/src/xtz.js +0 -409
package/dist/src/xtz.d.ts DELETED
@@ -1,125 +0,0 @@
1
- import { BaseCoin, BitGoBase, ParsedTransaction, ParseTransactionOptions, KeyPair as SdkCoreKeyPair, SignedTransaction, TransactionExplanation, VerifyAddressOptions, VerifyTransactionOptions, MultisigType, AuditDecryptedKeyParams } from '@bitgo-beta/sdk-core';
2
- import { CoinFamily, BaseCoin as StaticsBaseCoin } from '@bitgo-beta/statics';
3
- import { Interface } from './lib';
4
- import { RecoverOptions } from './lib/iface';
5
- export declare class Xtz extends BaseCoin {
6
- protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
7
- constructor(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>);
8
- static createInstance(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>): BaseCoin;
9
- getChain(): string;
10
- getFamily(): CoinFamily;
11
- getFullName(): string;
12
- getBaseFactor(): number;
13
- /** inherited doc */
14
- getDefaultMultisigType(): MultisigType;
15
- /**
16
- * Flag for sending value of 0
17
- * @returns {boolean} True if okay to send 0 value, false otherwise
18
- */
19
- valuelessTransferAllowed(): boolean;
20
- /**
21
- * Xtz supports transfers to consolidate balance from receive address to the wallet contract
22
- */
23
- allowsAccountConsolidations(): boolean;
24
- /**
25
- * Checks if this is a valid base58 or hex address
26
- * @param address
27
- */
28
- isValidAddress(address: string): boolean;
29
- /**
30
- * Generate Tezos key pair - BitGo xpub format
31
- *
32
- * @param seed
33
- * @returns {Object} object with generated xpub, xprv
34
- */
35
- generateKeyPair(seed?: Buffer): SdkCoreKeyPair;
36
- parseTransaction(params: ParseTransactionOptions): Promise<ParsedTransaction>;
37
- isWalletAddress(params: VerifyAddressOptions): Promise<boolean>;
38
- verifyTransaction(params: VerifyTransactionOptions): Promise<boolean>;
39
- /**
40
- * Derive a user key using the chain path of the address
41
- * @param key
42
- * @param path
43
- * @returns {string} derived private key
44
- */
45
- deriveKeyWithPath({ key, path }: {
46
- key: string;
47
- path: string;
48
- }): string;
49
- /**
50
- * Assemble keychain and half-sign prebuilt transaction
51
- *
52
- * @param params
53
- * @param params.txPrebuild {Object} prebuild object returned by platform
54
- * @param params.prv {String} user prv
55
- * @returns Bluebird<SignedTransaction>
56
- */
57
- signTransaction(params: Interface.XtzSignTransactionOptions): Promise<SignedTransaction>;
58
- /**
59
- * Sign message with private key
60
- *
61
- * @param key
62
- * @param message
63
- */
64
- signMessage(key: SdkCoreKeyPair, message: string | Buffer): Promise<Buffer>;
65
- /**
66
- * Method to validate recovery params
67
- * @param {RecoverOptions} params
68
- * @returns {void}
69
- */
70
- validateRecoveryParams(params: RecoverOptions): void;
71
- /**
72
- * Make a query to blockchain explorer for information such as balance, token balance, solidity calls
73
- * @param query {Object} key-value pairs of parameters to append after /api
74
- * @param apiKey {string} optional API key to use instead of the one from the environment
75
- * @returns {Object} response from the blockchain explorer
76
- */
77
- recoveryBlockchainExplorerQuery(params: {
78
- actionPath: string;
79
- address?: string;
80
- action?: string;
81
- }, apiKey?: string): Promise<unknown>;
82
- /**
83
- * Queries public block explorer to get the next XTZ address details
84
- * @param {string} address
85
- * @param {string} apiKey - optional API key to use instead of the one from the environment
86
- * @returns {Promise<any>}
87
- */
88
- getAddressDetails(address: string, apiKey?: string): Promise<any>;
89
- /**
90
- * Query explorer for the balance of an address
91
- * @param {String} address - the XTZ base/receive address
92
- * @param {String} apiKey - optional API key to use instead of the one from the environment
93
- * @returns {BigNumber} address balance
94
- */
95
- queryAddressBalance(address: string, apiKey?: string): Promise<any>;
96
- /**
97
- * Generate and pack the data to sign for each transfer.
98
- *
99
- * @param {String} contractAddress Wallet address to withdraw funds from
100
- * @param {String} contractCounter Wallet internal counter
101
- * @param {String} destination Tezos address to send the funds to
102
- * @param {String} amount Number of mutez to move
103
- * @param {IMSClient} imsClient Existing IMS client connection to reuse
104
- * @return {String} data to sign in hex format
105
- */
106
- packDataToSign(contractAddress: any, contractCounter: any, destination: any, amount: any): Promise<any>;
107
- /**
108
- * Builds a funds recovery transaction without BitGo.
109
- * We need to do three queries during this:
110
- * 1) Node query - how much money is in the account
111
- * 2) Build transaction - build our transaction for the amount
112
- * 3) Send signed build - send our signed build to a public node
113
- * @param params
114
- */
115
- recover(params: RecoverOptions): Promise<unknown>;
116
- /**
117
- * Explain a Tezos transaction from txHex
118
- * @param params
119
- */
120
- explainTransaction(params: Interface.ExplainTransactionOptions): Promise<TransactionExplanation>;
121
- isValidPub(pub: string): boolean;
122
- /** @inheritDoc */
123
- auditDecryptedKey(params: AuditDecryptedKeyParams): void;
124
- }
125
- //# sourceMappingURL=xtz.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"xtz.d.ts","sourceRoot":"","sources":["../../src/xtz.ts"],"names":[],"mappings":"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"}
package/dist/src/xtz.js DELETED
@@ -1,409 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Xtz = void 0;
7
- const sdk_core_1 = require("@bitgo-beta/sdk-core");
8
- const secp256k1_1 = require("@bitgo-beta/secp256k1");
9
- const statics_1 = require("@bitgo-beta/statics");
10
- const bignumber_js_1 = __importDefault(require("bignumber.js"));
11
- const lib_1 = require("./lib");
12
- const utils_1 = require("./lib/utils");
13
- const superagent_1 = __importDefault(require("superagent"));
14
- class Xtz extends sdk_core_1.BaseCoin {
15
- constructor(bitgo, staticsCoin) {
16
- super(bitgo);
17
- if (!staticsCoin) {
18
- throw new Error('missing required constructor parameter staticsCoin');
19
- }
20
- this._staticsCoin = staticsCoin;
21
- }
22
- static createInstance(bitgo, staticsCoin) {
23
- return new Xtz(bitgo, staticsCoin);
24
- }
25
- getChain() {
26
- return this._staticsCoin.name;
27
- }
28
- getFamily() {
29
- return this._staticsCoin.family;
30
- }
31
- getFullName() {
32
- return this._staticsCoin.fullName;
33
- }
34
- getBaseFactor() {
35
- return Math.pow(10, this._staticsCoin.decimalPlaces);
36
- }
37
- /** inherited doc */
38
- getDefaultMultisigType() {
39
- return sdk_core_1.multisigTypes.onchain;
40
- }
41
- /**
42
- * Flag for sending value of 0
43
- * @returns {boolean} True if okay to send 0 value, false otherwise
44
- */
45
- valuelessTransferAllowed() {
46
- return true;
47
- }
48
- /**
49
- * Xtz supports transfers to consolidate balance from receive address to the wallet contract
50
- */
51
- allowsAccountConsolidations() {
52
- return true;
53
- }
54
- /**
55
- * Checks if this is a valid base58 or hex address
56
- * @param address
57
- */
58
- isValidAddress(address) {
59
- if (!address) {
60
- return false;
61
- }
62
- return lib_1.Utils.isValidAddress(address);
63
- }
64
- /**
65
- * Generate Tezos key pair - BitGo xpub format
66
- *
67
- * @param seed
68
- * @returns {Object} object with generated xpub, xprv
69
- */
70
- generateKeyPair(seed) {
71
- const keyPair = seed ? new lib_1.KeyPair({ seed }) : new lib_1.KeyPair();
72
- const keys = keyPair.getExtendedKeys();
73
- if (!keys.xprv) {
74
- throw new Error('Missing xprv in key generation.');
75
- }
76
- return {
77
- pub: keys.xpub,
78
- prv: keys.xprv,
79
- };
80
- }
81
- async parseTransaction(params) {
82
- return {};
83
- }
84
- async isWalletAddress(params) {
85
- throw new sdk_core_1.MethodNotImplementedError();
86
- }
87
- async verifyTransaction(params) {
88
- const { txParams } = params;
89
- if (Array.isArray(txParams.recipients) && txParams.recipients.length > 1) {
90
- throw new Error(`${this.getChain()} doesn't support sending to more than 1 destination address within a single transaction. Try again, using only a single recipient.`);
91
- }
92
- return true;
93
- }
94
- /**
95
- * Derive a user key using the chain path of the address
96
- * @param key
97
- * @param path
98
- * @returns {string} derived private key
99
- */
100
- deriveKeyWithPath({ key, path }) {
101
- const keychain = secp256k1_1.bip32.fromBase58(key);
102
- const derivedKeyNode = keychain.derivePath(path);
103
- return derivedKeyNode.toBase58();
104
- }
105
- /**
106
- * Assemble keychain and half-sign prebuilt transaction
107
- *
108
- * @param params
109
- * @param params.txPrebuild {Object} prebuild object returned by platform
110
- * @param params.prv {String} user prv
111
- * @returns Bluebird<SignedTransaction>
112
- */
113
- async signTransaction(params) {
114
- const txBuilder = new lib_1.TransactionBuilder(statics_1.coins.get(this.getChain()));
115
- txBuilder.from(params.txPrebuild.txHex);
116
- txBuilder.source(params.txPrebuild.source);
117
- if (params.txPrebuild.dataToSign) {
118
- txBuilder.overrideDataToSign({ dataToSign: params.txPrebuild.dataToSign });
119
- }
120
- // The path /0/0/0/0 is used by the wallet base address
121
- // Derive the user key only if the transaction is sent from a receive address
122
- let key;
123
- const { chain, index } = params.txPrebuild.addressInfo;
124
- if (chain === 0 && index === 0) {
125
- key = params.prv;
126
- }
127
- else {
128
- const derivationPath = `0/0/${chain}/${index}`;
129
- key = this.deriveKeyWithPath({ key: params.prv, path: derivationPath });
130
- }
131
- txBuilder.sign({ key });
132
- const transaction = await txBuilder.build();
133
- if (!transaction) {
134
- throw new Error('Invalid messaged passed to signMessage');
135
- }
136
- const response = {
137
- txHex: transaction.toBroadcastFormat(),
138
- };
139
- return transaction.signature.length >= 2 ? response : { halfSigned: response };
140
- }
141
- /**
142
- * Sign message with private key
143
- *
144
- * @param key
145
- * @param message
146
- */
147
- async signMessage(key, message) {
148
- const keyPair = new lib_1.KeyPair({ prv: key.prv });
149
- const messageHex = message instanceof Buffer ? message.toString('hex') : Buffer.from(message, 'utf-8').toString('hex');
150
- const signatureData = await lib_1.Utils.sign(keyPair, messageHex);
151
- return Buffer.from(signatureData.sig);
152
- }
153
- /**
154
- * Method to validate recovery params
155
- * @param {RecoverOptions} params
156
- * @returns {void}
157
- */
158
- validateRecoveryParams(params) {
159
- if (params.userKey === undefined) {
160
- throw new Error('missing userKey');
161
- }
162
- if (params.backupKey === undefined) {
163
- throw new Error('missing backupKey');
164
- }
165
- if (!params.isUnsignedSweep && params.walletPassphrase === undefined && !params.userKey.startsWith('xpub')) {
166
- throw new Error('missing wallet passphrase');
167
- }
168
- if (params.walletContractAddress === undefined || !this.isValidAddress(params.walletContractAddress)) {
169
- throw new Error('invalid walletContractAddress');
170
- }
171
- if (params.recoveryDestination === undefined || !this.isValidAddress(params.recoveryDestination)) {
172
- throw new Error('invalid recoveryDestination');
173
- }
174
- }
175
- /**
176
- * Make a query to blockchain explorer for information such as balance, token balance, solidity calls
177
- * @param query {Object} key-value pairs of parameters to append after /api
178
- * @param apiKey {string} optional API key to use instead of the one from the environment
179
- * @returns {Object} response from the blockchain explorer
180
- */
181
- async recoveryBlockchainExplorerQuery(params, apiKey) {
182
- const response = await superagent_1.default.get(`${sdk_core_1.common.Environments[this.bitgo.getEnv()].xtzExplorerBaseUrl}/v1/${params.actionPath}${params.address ? '/' + params.address : ''}${params.action ? '/' + params.action : ''}${apiKey ? `?apikey=${apiKey}` : ''}`);
183
- if (!response.ok) {
184
- throw new Error('could not reach TZKT');
185
- }
186
- if (response.status === 429) {
187
- throw new Error('TZKT rate limit reached');
188
- }
189
- return response.body;
190
- }
191
- /**
192
- * Queries public block explorer to get the next XTZ address details
193
- * @param {string} address
194
- * @param {string} apiKey - optional API key to use instead of the one from the environment
195
- * @returns {Promise<any>}
196
- */
197
- async getAddressDetails(address, apiKey) {
198
- const result = await this.recoveryBlockchainExplorerQuery({
199
- actionPath: 'accounts',
200
- address,
201
- }, apiKey);
202
- if (!result) {
203
- throw new Error(`Unable to find details for ${address}`);
204
- }
205
- return result;
206
- }
207
- /**
208
- * Query explorer for the balance of an address
209
- * @param {String} address - the XTZ base/receive address
210
- * @param {String} apiKey - optional API key to use instead of the one from the environment
211
- * @returns {BigNumber} address balance
212
- */
213
- async queryAddressBalance(address, apiKey) {
214
- const result = await this.recoveryBlockchainExplorerQuery({
215
- actionPath: (0, utils_1.isValidOriginatedAddress)(address) ? 'contracts' : 'accounts',
216
- address,
217
- }, apiKey);
218
- // throw if the result does not exist or the result is not a valid number
219
- if (!result || !result.balance) {
220
- throw new Error(`Could not obtain address balance for ${address} from the explorer`);
221
- }
222
- return new bignumber_js_1.default(result.balance, 10);
223
- }
224
- /**
225
- * Generate and pack the data to sign for each transfer.
226
- *
227
- * @param {String} contractAddress Wallet address to withdraw funds from
228
- * @param {String} contractCounter Wallet internal counter
229
- * @param {String} destination Tezos address to send the funds to
230
- * @param {String} amount Number of mutez to move
231
- * @param {IMSClient} imsClient Existing IMS client connection to reuse
232
- * @return {String} data to sign in hex format
233
- */
234
- async packDataToSign(contractAddress, contractCounter, destination, amount) {
235
- const dataToSign = (0, utils_1.generateDataToSign)(contractAddress, destination, amount, contractCounter);
236
- const xtzRpcUrl = `${sdk_core_1.common.Environments[this.bitgo.getEnv()].xtzRpcUrl}/chains/main/blocks/head/helpers/scripts/pack_data`;
237
- if (!xtzRpcUrl) {
238
- throw new Error('XTZ RPC url not found');
239
- }
240
- const response = await superagent_1.default.post(xtzRpcUrl).send(dataToSign);
241
- if (response.status === 404) {
242
- throw new Error(`unable to pack data to sign ${response.status}: ${response.body.error.message}`);
243
- }
244
- else if (response.status !== 200) {
245
- throw new Error(`unexpected IMS response status ${response.status}: ${response.body.error.message}`);
246
- }
247
- return response.body.packed;
248
- }
249
- /**
250
- * Builds a funds recovery transaction without BitGo.
251
- * We need to do three queries during this:
252
- * 1) Node query - how much money is in the account
253
- * 2) Build transaction - build our transaction for the amount
254
- * 3) Send signed build - send our signed build to a public node
255
- * @param params
256
- */
257
- async recover(params) {
258
- const isUnsignedSweep = params.isUnsignedSweep;
259
- this.validateRecoveryParams(params);
260
- // Clean up whitespace from entered values
261
- const backupKey = params.backupKey.replace(/\s/g, '');
262
- const userAddressDetails = await this.getAddressDetails(params.walletContractAddress, params.apiKey);
263
- if (!userAddressDetails) {
264
- throw new Error('Unable to fetch user address details');
265
- }
266
- // Decrypt backup private key and get address
267
- let backupPrv;
268
- let keyPair;
269
- let backupSigningKey;
270
- if (isUnsignedSweep) {
271
- keyPair = new lib_1.KeyPair({ pub: backupKey });
272
- }
273
- else {
274
- try {
275
- backupPrv = this.bitgo.decrypt({
276
- input: backupKey,
277
- password: params.walletPassphrase,
278
- });
279
- }
280
- catch (e) {
281
- throw new Error(`Error decrypting backup keychain: ${e.message}`);
282
- }
283
- keyPair = new lib_1.KeyPair({ prv: backupPrv });
284
- backupSigningKey = keyPair.getKeys().prv;
285
- if (!backupSigningKey) {
286
- throw new Error('no private key');
287
- }
288
- }
289
- const backupKeyAddress = keyPair.getAddress();
290
- const backupAddressDetails = await this.getAddressDetails(backupKeyAddress, params.apiKey || '');
291
- if (!backupAddressDetails.counter || !backupAddressDetails.balance) {
292
- throw new Error(`Missing required detail(s) for ${backupKeyAddress}: counter, balance`);
293
- }
294
- const backupKeyNonce = new bignumber_js_1.default(backupAddressDetails.counter + 1, 10);
295
- // get balance of backupKey to ensure funds are available to pay fees
296
- const backupKeyBalance = new bignumber_js_1.default(backupAddressDetails.balance, 10);
297
- const gasLimit = (0, utils_1.isValidOriginatedAddress)(params.recoveryDestination)
298
- ? utils_1.TRANSACTION_GAS_LIMIT.CONTRACT_TRANSFER
299
- : utils_1.TRANSACTION_GAS_LIMIT.TRANSFER;
300
- const gasPrice = utils_1.TRANSACTION_FEE.TRANSFER;
301
- // Checking whether back up key address has sufficient funds for transaction
302
- if (backupKeyBalance.lt(gasPrice)) {
303
- const weiToGwei = 10 ** 6;
304
- throw new Error(`Backup key address ${backupKeyAddress} has balance ${(backupKeyBalance.toNumber() / weiToGwei).toString()} Gwei.` +
305
- `This address must have a balance of at least ${(gasPrice / weiToGwei).toString()}` +
306
- ` Gwei to perform recoveries. Try sending some funds to this address then retry.`);
307
- }
308
- // get balance of sender address
309
- if (!userAddressDetails.balance || userAddressDetails.balance === 0) {
310
- throw new Error('No funds to recover from source address');
311
- }
312
- const txAmount = userAddressDetails.balance;
313
- if (new bignumber_js_1.default(txAmount).isLessThanOrEqualTo(0)) {
314
- throw new Error('Wallet does not have enough funds to recover');
315
- }
316
- const feeInfo = {
317
- fee: new bignumber_js_1.default(utils_1.TRANSACTION_FEE.TRANSFER),
318
- gasLimit: new bignumber_js_1.default(gasLimit),
319
- storageLimit: new bignumber_js_1.default(utils_1.TRANSACTION_STORAGE_LIMIT.TRANSFER),
320
- };
321
- const txBuilder = new lib_1.TransactionBuilder(statics_1.coins.get(this.getChain()));
322
- txBuilder.type(sdk_core_1.TransactionType.Send);
323
- txBuilder.source(backupKeyAddress);
324
- // Used to set the branch for the transaction
325
- const chainHead = await this.recoveryBlockchainExplorerQuery({
326
- actionPath: 'head',
327
- });
328
- if (!chainHead || !chainHead.hash) {
329
- throw new Error('Unable to fetch chain head');
330
- }
331
- txBuilder.branch(chainHead.hash);
332
- if (!backupAddressDetails.revealed) {
333
- feeInfo.fee = feeInfo.fee.plus(utils_1.TRANSACTION_FEE.REVEAL);
334
- feeInfo.gasLimit = feeInfo.gasLimit.plus(utils_1.TRANSACTION_GAS_LIMIT.REVEAL);
335
- feeInfo.storageLimit = feeInfo.storageLimit.plus(utils_1.TRANSACTION_STORAGE_LIMIT.REVEAL);
336
- backupKeyNonce.plus(1);
337
- const publicKeyToReveal = keyPair.getKeys();
338
- txBuilder.publicKeyToReveal(publicKeyToReveal.pub);
339
- }
340
- txBuilder.counter(backupKeyNonce.toString());
341
- const packedDataToSign = await this.packDataToSign(params.walletContractAddress, backupKeyNonce.toString(), params.recoveryDestination, txAmount?.toString());
342
- txBuilder
343
- .transfer(txAmount?.toString())
344
- .from(params.walletContractAddress)
345
- .to(params.recoveryDestination)
346
- .counter(backupKeyNonce.toString())
347
- .fee(utils_1.TRANSACTION_FEE.TRANSFER.toString())
348
- .storageLimit(utils_1.TRANSACTION_STORAGE_LIMIT.TRANSFER.toString())
349
- .gasLimit(gasLimit.toString())
350
- .dataToSign(packedDataToSign);
351
- if (isUnsignedSweep) {
352
- const tx = await txBuilder.build();
353
- const txInfo = tx.toJson();
354
- return {
355
- txHex: tx.toBroadcastFormat(),
356
- txInfo,
357
- source: params.walletContractAddress,
358
- dataToSign: packedDataToSign,
359
- feeInfo,
360
- sourceCounter: backupKeyNonce.toString(),
361
- transferCounters: [backupKeyNonce.toString()],
362
- };
363
- }
364
- txBuilder.sign({ key: backupSigningKey });
365
- const signedTx = await txBuilder.build();
366
- return {
367
- id: signedTx.id,
368
- tx: signedTx.toBroadcastFormat(),
369
- };
370
- }
371
- /**
372
- * Explain a Tezos transaction from txHex
373
- * @param params
374
- */
375
- async explainTransaction(params) {
376
- const txHex = params.txHex || (params.halfSigned && params.halfSigned.txHex);
377
- if (!txHex || !params.feeInfo) {
378
- throw new Error('missing explain tx parameters');
379
- }
380
- const txBuilder = new lib_1.TransactionBuilder(statics_1.coins.get(this.getChain()));
381
- // Newer coins can return BaseTransactionBuilderFactory instead of BaseTransactionBuilder
382
- if (!(txBuilder instanceof sdk_core_1.BaseTransactionBuilder)) {
383
- throw new Error('getBuilder() did not return an BaseTransactionBuilder object. Has it been updated?');
384
- }
385
- txBuilder.from(txHex);
386
- const tx = await txBuilder.build();
387
- const displayOrder = ['id', 'outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee'];
388
- return {
389
- displayOrder,
390
- id: tx.id,
391
- outputs: tx.outputs,
392
- outputAmount: tx.outputs
393
- .reduce((accumulator, output) => accumulator.plus(output.value), new bignumber_js_1.default('0'))
394
- .toFixed(0),
395
- changeOutputs: [], // account based does not use change outputs
396
- changeAmount: '0', // account base does not make change
397
- fee: params.feeInfo,
398
- };
399
- }
400
- isValidPub(pub) {
401
- return lib_1.Utils.isValidPublicKey(pub);
402
- }
403
- /** @inheritDoc */
404
- auditDecryptedKey(params) {
405
- throw new sdk_core_1.MethodNotImplementedError();
406
- }
407
- }
408
- exports.Xtz = Xtz;
409
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieHR6LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3h0ei50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxtREFpQjhCO0FBQzlCLHFEQUE4QztBQUM5QyxpREFBcUY7QUFDckYsZ0VBQXFDO0FBQ3JDLCtCQUFzRTtBQUV0RSx1Q0FNcUI7QUFDckIsNERBQWlDO0FBQ2pDLE1BQWEsR0FBSSxTQUFRLG1CQUFRO0lBRy9CLFlBQVksS0FBZ0IsRUFBRSxXQUF1QztRQUNuRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFYixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1FBQ3hFLENBQUM7UUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQztJQUNsQyxDQUFDO0lBRUQsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFnQixFQUFFLFdBQXVDO1FBQzdFLE9BQU8sSUFBSSxHQUFHLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRCxRQUFRO1FBQ04sT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQztJQUNoQyxDQUFDO0lBRUQsU0FBUztRQUNQLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUM7SUFDbEMsQ0FBQztJQUVELFdBQVc7UUFDVCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxhQUFhO1FBQ1gsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFRCxvQkFBb0I7SUFDcEIsc0JBQXNCO1FBQ3BCLE9BQU8sd0JBQWEsQ0FBQyxPQUFPLENBQUM7SUFDL0IsQ0FBQztJQUVEOzs7T0FHRztJQUNILHdCQUF3QjtRQUN0QixPQUFPLElB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Q0FBQyxLQUFLLEVBQUUsQ0FBQztRQUVuQyxNQUFNLFlBQVksR0FBRyxDQUFDLElBQUksRUFBRSxjQUFjLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFL0YsT0FBTztZQUNMLFlBQVk7WUFDWixFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUU7WUFDVCxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU87WUFDbkIsWUFBWSxFQUFFLEVBQUUsQ0FBQyxPQUFPO2lCQUNyQixNQUFNLENBQUMsQ0FBQyxXQUFXLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLHNCQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7aUJBQ25GLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDYixhQUFhLEVBQUUsRUFBRSxFQUFFLDRDQUE0QztZQUMvRCxZQUFZLEVBQUUsR0FBRyxFQUFFLG9DQUFvQztZQUN2RCxHQUFHLEVBQUUsTUFBTSxDQUFDLE9BQU87U0FDYixDQUFDO0lBQ1gsQ0FBQztJQUVELFVBQVUsQ0FBQyxHQUFXO1FBQ3BCLE9BQU8sV0FBSyxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsaUJBQWlCLENBQUMsTUFBK0I7UUFDL0MsTUFBTSxJQUFJLG9DQUF5QixFQUFFLENBQUM7SUFDeEMsQ0FBQztDQUNGO0FBdGVELGtCQXNlQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEJhc2VDb2luLFxuICBCYXNlVHJhbnNhY3Rpb25CdWlsZGVyLFxuICBCaXRHb0Jhc2UsXG4gIE1ldGhvZE5vdEltcGxlbWVudGVkRXJyb3IsXG4gIFBhcnNlZFRyYW5zYWN0aW9uLFxuICBQYXJzZVRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgS2V5UGFpciBhcyBTZGtDb3JlS2V5UGFpcixcbiAgU2lnbmVkVHJhbnNhY3Rpb24sXG4gIFRyYW5zYWN0aW9uRXhwbGFuYXRpb24sXG4gIFZlcmlmeUFkZHJlc3NPcHRpb25zLFxuICBWZXJpZnlUcmFuc2FjdGlvbk9wdGlvbnMsXG4gIE11bHRpc2lnVHlwZSxcbiAgbXVsdGlzaWdUeXBlcyxcbiAgQXVkaXREZWNyeXB0ZWRLZXlQYXJhbXMsXG4gIGNvbW1vbixcbiAgVHJhbnNhY3Rpb25UeXBlLFxufSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBiaXAzMiB9IGZyb20gJ0BiaXRnby1iZXRhL3NlY3AyNTZrMSc7XG5pbXBvcnQgeyBDb2luRmFtaWx5LCBjb2lucywgQmFzZUNvaW4gYXMgU3RhdGljc0Jhc2VDb2luIH0gZnJvbSAnQGJpdGdvLWJldGEvc3RhdGljcyc7XG5pbXBvcnQgQmlnTnVtYmVyIGZyb20gJ2JpZ251bWJlci5qcyc7XG5pbXBvcnQgeyBJbnRlcmZhY2UsIEtleVBhaXIsIFRyYW5zYWN0aW9uQnVpbGRlciwgVXRpbHMgfSBmcm9tICcuL2xpYic7XG5pbXBvcnQgeyBSZWNvdmVyT3B0aW9ucyB9IGZyb20gJy4vbGliL2lmYWNlJztcbmltcG9ydCB7XG4gIGdlbmVyYXRlRGF0YVRvU2lnbixcbiAgaXNWYWxpZE9yaWdpbmF0ZWRBZGRyZXNzLFxuICBUUkFOU0FDVElPTl9GRUUsXG4gIFRSQU5TQUNUSU9OX0dBU19MSU1JVCxcbiAgVFJBTlNBQ1RJT05fU1RPUkFHRV9MSU1JVCxcbn0gZnJvbSAnLi9saWIvdXRpbHMnO1xuaW1wb3J0IHJlcXVlc3QgZnJvbSAnc3VwZXJhZ2VudCc7XG5leHBvcnQgY2xhc3MgWHR6IGV4dGVuZHMgQmFzZUNvaW4ge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgX3N0YXRpY3NDb2luOiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+O1xuXG4gIGNvbnN0cnVjdG9yKGJpdGdvOiBCaXRHb0Jhc2UsIHN0YXRpY3NDb2luPzogUmVhZG9ubHk8U3RhdGljc0Jhc2VDb2luPikge1xuICAgIHN1cGVyKGJpdGdvKTtcblxuICAgIGlmICghc3RhdGljc0NvaW4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyByZXF1aXJlZCBjb25zdHJ1Y3RvciBwYXJhbWV0ZXIgc3RhdGljc0NvaW4nKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zdGF0aWNzQ29pbiA9IHN0YXRpY3NDb2luO1xuICB9XG5cbiAgc3RhdGljIGNyZWF0ZUluc3RhbmNlKGJpdGdvOiBCaXRHb0Jhc2UsIHN0YXRpY3NDb2luPzogUmVhZG9ubHk8U3RhdGljc0Jhc2VDb2luPik6IEJhc2VDb2luIHtcbiAgICByZXR1cm4gbmV3IFh0eihiaXRnbywgc3RhdGljc0NvaW4pO1xuICB9XG5cbiAgZ2V0Q2hhaW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4ubmFtZTtcbiAgfVxuXG4gIGdldEZhbWlseSgpOiBDb2luRmFtaWx5IHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4uZmFtaWx5O1xuICB9XG5cbiAgZ2V0RnVsbE5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4uZnVsbE5hbWU7XG4gIH1cblxuICBnZXRCYXNlRmFjdG9yKCkge1xuICAgIHJldHVybiBNYXRoLnBvdygxMCwgdGhpcy5fc3RhdGljc0NvaW4uZGVjaW1hbFBsYWNlcyk7XG4gIH1cblxuICAvKiogaW5oZXJpdGVkIGRvYyAqL1xuICBnZXREZWZhdWx0TXVsdGlzaWdUeXBlKCk6IE11bHRpc2lnVHlwZSB7XG4gICAgcmV0dXJuIG11bHRpc2lnVHlwZXMub25jaGFpbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGFnIGZvciBzZW5kaW5nIHZhbHVlIG9mIDBcbiAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgb2theSB0byBzZW5kIDAgdmFsdWUsIGZhbHNlIG90aGVyd2lzZVxuICAgKi9cbiAgdmFsdWVsZXNzVHJhbnNmZXJBbGxvd2VkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFh0eiBzdXBwb3J0cyB0cmFuc2ZlcnMgdG8gY29uc29saWRhdGUgYmFsYW5jZSBmcm9tIHJlY2VpdmUgYWRkcmVzcyB0byB0aGUgd2FsbGV0IGNvbnRyYWN0XG4gICAqL1xuICBhbGxvd3NBY2NvdW50Q29uc29saWRhdGlvbnMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoaXMgaXMgYSB2YWxpZCBiYXNlNTggb3IgaGV4IGFkZHJlc3NcbiAgICogQHBhcmFtIGFkZHJlc3NcbiAgICovXG4gIGlzVmFsaWRBZGRyZXNzKGFkZHJlc3M6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGlmICghYWRkcmVzcykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gVXRpbHMuaXNWYWxpZEFkZHJlc3MoYWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGUgVGV6b3Mga2V5IHBhaXIgLSBCaXRHbyB4cHViIGZvcm1hdFxuICAgKlxuICAgKiBAcGFyYW0gc2VlZFxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBvYmplY3Qgd2l0aCBnZW5lcmF0ZWQgeHB1YiwgeHBydlxuICAgKi9cbiAgZ2VuZXJhdGVLZXlQYWlyKHNlZWQ/OiBCdWZmZXIpOiBTZGtDb3JlS2V5UGFpciB7XG4gICAgY29uc3Qga2V5UGFpciA9IHNlZWQgPyBuZXcgS2V5UGFpcih7IHNlZWQgfSkgOiBuZXcgS2V5UGFpcigpO1xuICAgIGNvbnN0IGtleXMgPSBrZXlQYWlyLmdldEV4dGVuZGVkS2V5cygpO1xuXG4gICAgaWYgKCFrZXlzLnhwcnYpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyB4cHJ2IGluIGtleSBnZW5lcmF0aW9uLicpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBwdWI6IGtleXMueHB1YixcbiAgICAgIHBydjoga2V5cy54cHJ2LFxuICAgIH07XG4gIH1cblxuICBhc3luYyBwYXJzZVRyYW5zYWN0aW9uKHBhcmFtczogUGFyc2VUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFBhcnNlZFRyYW5zYWN0aW9uPiB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgYXN5bmMgaXNXYWxsZXRBZGRyZXNzKHBhcmFtczogVmVyaWZ5QWRkcmVzc09wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICB0aHJvdyBuZXcgTWV0aG9kTm90SW1wbGVtZW50ZWRFcnJvcigpO1xuICB9XG5cbiAgYXN5bmMgdmVyaWZ5VHJhbnNhY3Rpb24ocGFyYW1zOiBWZXJpZnlUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCB7IHR4UGFyYW1zIH0gPSBwYXJhbXM7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodHhQYXJhbXMucmVjaXBpZW50cykgJiYgdHhQYXJhbXMucmVjaXBpZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke3RoaXMuZ2V0Q2hhaW4oKX0gZG9lc24ndCBzdXBwb3J0IHNlbmRpbmcgdG8gbW9yZSB0aGFuIDEgZGVzdGluYXRpb24gYWRkcmVzcyB3aXRoaW4gYSBzaW5nbGUgdHJhbnNhY3Rpb24uIFRyeSBhZ2FpbiwgdXNpbmcgb25seSBhIHNpbmdsZSByZWNpcGllbnQuYFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogRGVyaXZlIGEgdXNlciBrZXkgdXNpbmcgdGhlIGNoYWluIHBhdGggb2YgdGhlIGFkZHJlc3NcbiAgICogQHBhcmFtIGtleVxuICAgKiBAcGFyYW0gcGF0aFxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBkZXJpdmVkIHByaXZhdGUga2V5XG4gICAqL1xuICBkZXJpdmVLZXlXaXRoUGF0aCh7IGtleSwgcGF0aCB9OiB7IGtleTogc3RyaW5nOyBwYXRoOiBzdHJpbmcgfSk6IHN0cmluZyB7XG4gICAgY29uc3Qga2V5Y2hhaW4gPSBiaXAzMi5mcm9tQmFzZTU4KGtleSk7XG4gICAgY29uc3QgZGVyaXZlZEtleU5vZGUgPSBrZXljaGFpbi5kZXJpdmVQYXRoKHBhdGgpO1xuICAgIHJldHVybiBkZXJpdmVkS2V5Tm9kZS50b0Jhc2U1OCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFzc2VtYmxlIGtleWNoYWluIGFuZCBoYWxmLXNpZ24gcHJlYnVpbHQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKiBAcGFyYW0gcGFyYW1zLnR4UHJlYnVpbGQge09iamVjdH0gcHJlYnVpbGQgb2JqZWN0IHJldHVybmVkIGJ5IHBsYXRmb3JtXG4gICAqIEBwYXJhbSBwYXJhbXMucHJ2IHtTdHJpbmd9IHVzZXIgcHJ2XG4gICAqIEByZXR1cm5zIEJsdWViaXJkPFNpZ25lZFRyYW5zYWN0aW9uPlxuICAgKi9cbiAgYXN5bmMgc2lnblRyYW5zYWN0aW9uKHBhcmFtczogSW50ZXJmYWNlLlh0elNpZ25UcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFNpZ25lZFRyYW5zYWN0aW9uPiB7XG4gICAgY29uc3QgdHhCdWlsZGVyID0gbmV3IFRyYW5zYWN0aW9uQnVpbGRlcihjb2lucy5nZXQodGhpcy5nZXRDaGFpbigpKSk7XG4gICAgdHhCdWlsZGVyLmZyb20ocGFyYW1zLnR4UHJlYnVpbGQudHhIZXgpO1xuICAgIHR4QnVpbGRlci5zb3VyY2UocGFyYW1zLnR4UHJlYnVpbGQuc291cmNlKTtcbiAgICBpZiAocGFyYW1zLnR4UHJlYnVpbGQuZGF0YVRvU2lnbikge1xuICAgICAgdHhCdWlsZGVyLm92ZXJyaWRlRGF0YVRvU2lnbih7IGRhdGFUb1NpZ246IHBhcmFtcy50eFByZWJ1aWxkLmRhdGFUb1NpZ24gfSk7XG4gICAgfVxuICAgIC8vIFRoZSBwYXRoIC8wLzAvMC8wIGlzIHVzZWQgYnkgdGhlIHdhbGxldCBiYXNlIGFkZHJlc3NcbiAgICAvLyBEZXJpdmUgdGhlIHVzZXIga2V5IG9ubHkgaWYgdGhlIHRyYW5zYWN0aW9uIGlzIHNlbnQgZnJvbSBhIHJlY2VpdmUgYWRkcmVzc1xuICAgIGxldCBrZXk7XG4gICAgY29uc3QgeyBjaGFpbiwgaW5kZXggfSA9IHBhcmFtcy50eFByZWJ1aWxkLmFkZHJlc3NJbmZvO1xuICAgIGlmIChjaGFpbiA9PT0gMCAmJiBpbmRleCA9PT0gMCkge1xuICAgICAga2V5ID0gcGFyYW1zLnBydjtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgZGVyaXZhdGlvblBhdGggPSBgMC8wLyR7Y2hhaW59LyR7aW5kZXh9YDtcbiAgICAgIGtleSA9IHRoaXMuZGVyaXZlS2V5V2l0aFBhdGgoeyBrZXk6IHBhcmFtcy5wcnYsIHBhdGg6IGRlcml2YXRpb25QYXRoIH0pO1xuICAgIH1cbiAgICB0eEJ1aWxkZXIuc2lnbih7IGtleSB9KTtcblxuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgaWYgKCF0cmFuc2FjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1lc3NhZ2VkIHBhc3NlZCB0byBzaWduTWVzc2FnZScpO1xuICAgIH1cbiAgICBjb25zdCByZXNwb25zZSA9IHtcbiAgICAgIHR4SGV4OiB0cmFuc2FjdGlvbi50b0Jyb2FkY2FzdEZvcm1hdCgpLFxuICAgIH07XG4gICAgcmV0dXJuIHRyYW5zYWN0aW9uLnNpZ25hdHVyZS5sZW5ndGggPj0gMiA/IHJlc3BvbnNlIDogeyBoYWxmU2lnbmVkOiByZXNwb25zZSB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFNpZ24gbWVzc2FnZSB3aXRoIHByaXZhdGUga2V5XG4gICAqXG4gICAqIEBwYXJhbSBrZXlcbiAgICogQHBhcmFtIG1lc3NhZ2VcbiAgICovXG4gIGFzeW5jIHNpZ25NZXNzYWdlKGtleTogU2RrQ29yZUtleVBhaXIsIG1lc3NhZ2U6IHN0cmluZyB8IEJ1ZmZlcik6IFByb21pc2U8QnVmZmVyPiB7XG4gICAgY29uc3Qga2V5UGFpciA9IG5ldyBLZXlQYWlyKHsgcHJ2OiBrZXkucHJ2IH0pO1xuICAgIGNvbnN0IG1lc3NhZ2VIZXggPVxuICAgICAgbWVzc2FnZSBpbnN0YW5jZW9mIEJ1ZmZlciA/IG1lc3NhZ2UudG9TdHJpbmcoJ2hleCcpIDogQnVmZmVyLmZyb20obWVzc2FnZSBhcyBzdHJpbmcsICd1dGYtOCcpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBjb25zdCBzaWduYXR1cmVEYXRhID0gYXdhaXQgVXRpbHMuc2lnbihrZXlQYWlyLCBtZXNzYWdlSGV4KTtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oc2lnbmF0dXJlRGF0YS5zaWcpO1xuICB9XG4gIC8qKlxuICAgKiBNZXRob2QgdG8gdmFsaWRhdGUgcmVjb3ZlcnkgcGFyYW1zXG4gICAqIEBwYXJhbSB7UmVjb3Zlck9wdGlvbnN9IHBhcmFtc1xuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHZhbGlkYXRlUmVjb3ZlcnlQYXJhbXMocGFyYW1zOiBSZWNvdmVyT3B0aW9ucyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMudXNlcktleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgdXNlcktleScpO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXMuYmFja3VwS2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBiYWNrdXBLZXknKTtcbiAgICB9XG5cbiAgICBpZiAoIXBhcmFtcy5pc1Vuc2lnbmVkU3dlZXAgJiYgcGFyYW1zLndhbGxldFBhc3NwaHJhc2UgPT09IHVuZGVmaW5lZCAmJiAhcGFyYW1zLnVzZXJLZXkuc3RhcnRzV2l0aCgneHB1YicpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3Npbmcgd2FsbGV0IHBhc3NwaHJhc2UnKTtcbiAgICB9XG5cbiAgICBpZiAocGFyYW1zLndhbGxldENvbnRyYWN0QWRkcmVzcyA9PT0gdW5kZWZpbmVkIHx8ICF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgd2FsbGV0Q29udHJhY3RBZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgaWYgKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uID09PSB1bmRlZmluZWQgfHwgIXRoaXMuaXNWYWxpZEFkZHJlc3MocGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgcmVjb3ZlcnlEZXN0aW5hdGlvbicpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNYWtlIGEgcXVlcnkgdG8gYmxvY2tjaGFpbiBleHBsb3JlciBmb3IgaW5mb3JtYXRpb24gc3VjaCBhcyBiYWxhbmNlLCB0b2tlbiBiYWxhbmNlLCBzb2xpZGl0eSBjYWxsc1xuICAgKiBAcGFyYW0gcXVlcnkge09iamVjdH0ga2V5LXZhbHVlIHBhaXJzIG9mIHBhcmFtZXRlcnMgdG8gYXBwZW5kIGFmdGVyIC9hcGlcbiAgICogQHBhcmFtIGFwaUtleSB7c3RyaW5nfSBvcHRpb25hbCBBUEkga2V5IHRvIHVzZSBpbnN0ZWFkIG9mIHRoZSBvbmUgZnJvbSB0aGUgZW52aXJvbm1lbnRcbiAgICogQHJldHVybnMge09iamVjdH0gcmVzcG9uc2UgZnJvbSB0aGUgYmxvY2tjaGFpbiBleHBsb3JlclxuICAgKi9cbiAgYXN5bmMgcmVjb3ZlcnlCbG9ja2NoYWluRXhwbG9yZXJRdWVyeShcbiAgICBwYXJhbXM6IHtcbiAgICAgIGFjdGlvblBhdGg6IHN0cmluZztcbiAgICAgIGFkZHJlc3M/OiBzdHJpbmc7XG4gICAgICBhY3Rpb24/OiBzdHJpbmc7XG4gICAgfSxcbiAgICBhcGlLZXk/OiBzdHJpbmdcbiAgKTogUHJvbWlzZTx1bmtub3duPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0LmdldChcbiAgICAgIGAke2NvbW1vbi5FbnZpcm9ubWVudHNbdGhpcy5iaXRnby5nZXRFbnYoKV0ueHR6RXhwbG9yZXJCYXNlVXJsfS92MS8ke3BhcmFtcy5hY3Rpb25QYXRofSR7XG4gICAgICAgIHBhcmFtcy5hZGRyZXNzID8gJy8nICsgcGFyYW1zLmFkZHJlc3MgOiAnJ1xuICAgICAgfSR7cGFyYW1zLmFjdGlvbiA/ICcvJyArIHBhcmFtcy5hY3Rpb24gOiAnJ30ke2FwaUtleSA/IGA/YXBpa2V5PSR7YXBpS2V5fWAgOiAnJ31gXG4gICAgKTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHJlYWNoIFRaS1QnKTtcbiAgICB9XG5cbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSA0MjkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVFpLVCByYXRlIGxpbWl0IHJlYWNoZWQnKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3BvbnNlLmJvZHk7XG4gIH1cblxuICAvKipcbiAgICogUXVlcmllcyBwdWJsaWMgYmxvY2sgZXhwbG9yZXIgdG8gZ2V0IHRoZSBuZXh0IFhUWiBhZGRyZXNzIGRldGFpbHNcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3NcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFwaUtleSAtIG9wdGlvbmFsIEFQSSBrZXkgdG8gdXNlIGluc3RlYWQgb2YgdGhlIG9uZSBmcm9tIHRoZSBlbnZpcm9ubWVudFxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxhbnk+fVxuICAgKi9cbiAgYXN5bmMgZ2V0QWRkcmVzc0RldGFpbHMoYWRkcmVzczogc3RyaW5nLCBhcGlLZXk/OiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMucmVjb3ZlcnlCbG9ja2NoYWluRXhwbG9yZXJRdWVyeShcbiAgICAgIHtcbiAgICAgICAgYWN0aW9uUGF0aDogJ2FjY291bnRzJyxcbiAgICAgICAgYWRkcmVzcyxcbiAgICAgIH0sXG4gICAgICBhcGlLZXlcbiAgICApO1xuXG4gICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGZpbmQgZGV0YWlscyBmb3IgJHthZGRyZXNzfWApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFF1ZXJ5IGV4cGxvcmVyIGZvciB0aGUgYmFsYW5jZSBvZiBhbiBhZGRyZXNzXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBhZGRyZXNzIC0gdGhlIFhUWiBiYXNlL3JlY2VpdmUgYWRkcmVzc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gYXBpS2V5IC0gb3B0aW9uYWwgQVBJIGtleSB0byB1c2UgaW5zdGVhZCBvZiB0aGUgb25lIGZyb20gdGhlIGVudmlyb25tZW50XG4gICAqIEByZXR1cm5zIHtCaWdOdW1iZXJ9IGFkZHJlc3MgYmFsYW5jZVxuICAgKi9cbiAgYXN5bmMgcXVlcnlBZGRyZXNzQmFsYW5jZShhZGRyZXNzOiBzdHJpbmcsIGFwaUtleT86IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgcmVzdWx0OiBhbnkgPSBhd2FpdCB0aGlzLnJlY292ZXJ5QmxvY2tjaGFpbkV4cGxvcmVyUXVlcnkoXG4gICAgICB7XG4gICAgICAgIGFjdGlvblBhdGg6IGlzVmFsaWRPcmlnaW5hdGVkQWRkcmVzcyhhZGRyZXNzKSA/ICdjb250cmFjdHMnIDogJ2FjY291bnRzJyxcbiAgICAgICAgYWRkcmVzcyxcbiAgICAgIH0sXG4gICAgICBhcGlLZXlcbiAgICApO1xuICAgIC8vIHRocm93IGlmIHRoZSByZXN1bHQgZG9lcyBub3QgZXhpc3Qgb3IgdGhlIHJlc3VsdCBpcyBub3QgYSB2YWxpZCBudW1iZXJcbiAgICBpZiAoIXJlc3VsdCB8fCAhcmVzdWx0LmJhbGFuY2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IG9idGFpbiBhZGRyZXNzIGJhbGFuY2UgZm9yICR7YWRkcmVzc30gZnJvbSB0aGUgZXhwbG9yZXJgKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBCaWdOdW1iZXIocmVzdWx0LmJhbGFuY2UsIDEwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBhbmQgcGFjayB0aGUgZGF0YSB0byBzaWduIGZvciBlYWNoIHRyYW5zZmVyLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gY29udHJhY3RBZGRyZXNzIFdhbGxldCBhZGRyZXNzIHRvIHdpdGhkcmF3IGZ1bmRzIGZyb21cbiAgICogQHBhcmFtIHtTdHJpbmd9IGNvbnRyYWN0Q291bnRlciBXYWxsZXQgaW50ZXJuYWwgY291bnRlclxuICAgKiBAcGFyYW0ge1N0cmluZ30gZGVzdGluYXRpb24gVGV6b3MgYWRkcmVzcyB0byBzZW5kIHRoZSBmdW5kcyB0b1xuICAgKiBAcGFyYW0ge1N0cmluZ30gYW1vdW50IE51bWJlciBvZiBtdXRleiB0byBtb3ZlXG4gICAqIEBwYXJhbSB7SU1TQ2xpZW50fSBpbXNDbGllbnQgRXhpc3RpbmcgSU1TIGNsaWVudCBjb25uZWN0aW9uIHRvIHJldXNlXG4gICAqIEByZXR1cm4ge1N0cmluZ30gZGF0YSB0byBzaWduIGluIGhleCBmb3JtYXRcbiAgICovXG4gIGFzeW5jIHBhY2tEYXRhVG9TaWduKGNvbnRyYWN0QWRkcmVzcywgY29udHJhY3RDb3VudGVyLCBkZXN0aW5hdGlvbiwgYW1vdW50KSB7XG4gICAgY29uc3QgZGF0YVRvU2lnbiA9IGdlbmVyYXRlRGF0YVRvU2lnbihjb250cmFjdEFkZHJlc3MsIGRlc3RpbmF0aW9uLCBhbW91bnQsIGNvbnRyYWN0Q291bnRlcik7XG4gICAgY29uc3QgeHR6UnBjVXJsID0gYCR7XG4gICAgICBjb21tb24uRW52aXJvbm1lbnRzW3RoaXMuYml0Z28uZ2V0RW52KCldLnh0elJwY1VybFxuICAgIH0vY2hhaW5zL21haW4vYmxvY2tzL2hlYWQvaGVscGVycy9zY3JpcHRzL3BhY2tfZGF0YWA7XG5cbiAgICBpZiAoIXh0elJwY1VybCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdYVFogUlBDIHVybCBub3QgZm91bmQnKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHJlcXVlc3QucG9zdCh4dHpScGNVcmwpLnNlbmQoZGF0YVRvU2lnbik7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gNDA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuYWJsZSB0byBwYWNrIGRhdGEgdG8gc2lnbiAke3Jlc3BvbnNlLnN0YXR1c306ICR7cmVzcG9uc2UuYm9keS5lcnJvci5tZXNzYWdlfWApO1xuICAgIH0gZWxzZSBpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5leHBlY3RlZCBJTVMgcmVzcG9uc2Ugc3RhdHVzICR7cmVzcG9uc2Uuc3RhdHVzfTogJHtyZXNwb25zZS5ib2R5LmVycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICAgIHJldHVybiByZXNwb25zZS5ib2R5LnBhY2tlZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgYSBmdW5kcyByZWNvdmVyeSB0cmFuc2FjdGlvbiB3aXRob3V0IEJpdEdvLlxuICAgKiBXZSBuZWVkIHRvIGRvIHRocmVlIHF1ZXJpZXMgZHVyaW5nIHRoaXM6XG4gICAqIDEpIE5vZGUgcXVlcnkgLSBob3cgbXVjaCBtb25leSBpcyBpbiB0aGUgYWNjb3VudFxuICAgKiAyKSBCdWlsZCB0cmFuc2FjdGlvbiAtIGJ1aWxkIG91ciB0cmFuc2FjdGlvbiBmb3IgdGhlIGFtb3VudFxuICAgKiAzKSBTZW5kIHNpZ25lZCBidWlsZCAtIHNlbmQgb3VyIHNpZ25lZCBidWlsZCB0byBhIHB1YmxpYyBub2RlXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICovXG4gIGFzeW5jIHJlY292ZXIocGFyYW1zOiBSZWNvdmVyT3B0aW9ucyk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgIGNvbnN0IGlzVW5zaWduZWRTd2VlcCA9IHBhcmFtcy5pc1Vuc2lnbmVkU3dlZXA7XG4gICAgdGhpcy52YWxpZGF0ZVJlY292ZXJ5UGFyYW1zKHBhcmFtcyk7XG5cbiAgICAvLyBDbGVhbiB1cCB3aGl0ZXNwYWNlIGZyb20gZW50ZXJlZCB2YWx1ZXNcbiAgICBjb25zdCBiYWNrdXBLZXkgPSBwYXJhbXMuYmFja3VwS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG5cbiAgICBjb25zdCB1c2VyQWRkcmVzc0RldGFpbHMgPSBhd2FpdCB0aGlzLmdldEFkZHJlc3NEZXRhaWxzKHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MsIHBhcmFtcy5hcGlLZXkpO1xuXG4gICAgaWYgKCF1c2VyQWRkcmVzc0RldGFpbHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGZldGNoIHVzZXIgYWRkcmVzcyBkZXRhaWxzJyk7XG4gICAgfVxuXG4gICAgLy8gRGVjcnlwdCBiYWNrdXAgcHJpdmF0ZSBrZXkgYW5kIGdldCBhZGRyZXNzXG4gICAgbGV0IGJhY2t1cFBydjtcbiAgICBsZXQga2V5UGFpcjtcbiAgICBsZXQgYmFja3VwU2lnbmluZ0tleTtcblxuICAgIGlmIChpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgIGtleVBhaXIgPSBuZXcgS2V5UGFpcih7IHB1YjogYmFja3VwS2V5IH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cnkge1xuICAgICAgICBiYWNrdXBQcnYgPSB0aGlzLmJpdGdvLmRlY3J5cHQoe1xuICAgICAgICAgIGlucHV0OiBiYWNrdXBLZXksXG4gICAgICAgICAgcGFzc3dvcmQ6IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBkZWNyeXB0aW5nIGJhY2t1cCBrZXljaGFpbjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgICB9XG4gICAgICBrZXlQYWlyID0gbmV3IEtleVBhaXIoeyBwcnY6IGJhY2t1cFBydiB9KTtcbiAgICAgIGJhY2t1cFNpZ25pbmdLZXkgPSBrZXlQYWlyLmdldEtleXMoKS5wcnY7XG4gICAgICBpZiAoIWJhY2t1cFNpZ25pbmdLZXkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyBwcml2YXRlIGtleScpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGJhY2t1cEtleUFkZHJlc3MgPSBrZXlQYWlyLmdldEFkZHJlc3MoKTtcbiAgICBjb25zdCBiYWNrdXBBZGRyZXNzRGV0YWlscyA9IGF3YWl0IHRoaXMuZ2V0QWRkcmVzc0RldGFpbHMoYmFja3VwS2V5QWRkcmVzcywgcGFyYW1zLmFwaUtleSB8fCAnJyk7XG5cbiAgICBpZiAoIWJhY2t1cEFkZHJlc3NEZXRhaWxzLmNvdW50ZXIgfHwgIWJhY2t1cEFkZHJlc3NEZXRhaWxzLmJhbGFuY2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyByZXF1aXJlZCBkZXRhaWwocykgZm9yICR7YmFja3VwS2V5QWRkcmVzc306IGNvdW50ZXIsIGJhbGFuY2VgKTtcbiAgICB9XG4gICAgY29uc3QgYmFja3VwS2V5Tm9uY2UgPSBuZXcgQmlnTnVtYmVyKGJhY2t1cEFkZHJlc3NEZXRhaWxzLmNvdW50ZXIgKyAxLCAxMCk7XG5cbiAgICAvLyBnZXQgYmFsYW5jZSBvZiBiYWNrdXBLZXkgdG8gZW5zdXJlIGZ1bmRzIGFyZSBhdmFpbGFibGUgdG8gcGF5IGZlZXNcbiAgICBjb25zdCBiYWNrdXBLZXlCYWxhbmNlID0gbmV3IEJpZ051bWJlcihiYWNrdXBBZGRyZXNzRGV0YWlscy5iYWxhbmNlLCAxMCk7XG5cbiAgICBjb25zdCBnYXNMaW1pdCA9IGlzVmFsaWRPcmlnaW5hdGVkQWRkcmVzcyhwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbilcbiAgICAgID8gVFJBTlNBQ1RJT05fR0FTX0xJTUlULkNPTlRSQUNUX1RSQU5TRkVSXG4gICAgICA6IFRSQU5TQUNUSU9OX0dBU19MSU1JVC5UUkFOU0ZFUjtcbiAgICBjb25zdCBnYXNQcmljZSA9IFRSQU5TQUNUSU9OX0ZFRS5UUkFOU0ZFUjtcblxuICAgIC8vIENoZWNraW5nIHdoZXRoZXIgYmFjayB1cCBrZXkgYWRkcmVzcyBoYXMgc3VmZmljaWVudCBmdW5kcyBmb3IgdHJhbnNhY3Rpb25cbiAgICBpZiAoYmFja3VwS2V5QmFsYW5jZS5sdChnYXNQcmljZSkpIHtcbiAgICAgIGNvbnN0IHdlaVRvR3dlaSA9IDEwICoqIDY7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBCYWNrdXAga2V5IGFkZHJlc3MgJHtiYWNrdXBLZXlBZGRyZXNzfSBoYXMgYmFsYW5jZSAkeyhcbiAgICAgICAgICBiYWNrdXBLZXlCYWxhbmNlLnRvTnVtYmVyKCkgLyB3ZWlUb0d3ZWlcbiAgICAgICAgKS50b1N0cmluZygpfSBHd2VpLmAgK1xuICAgICAgICAgIGBUaGlzIGFkZHJlc3MgbXVzdCBoYXZlIGEgYmFsYW5jZSBvZiBhdCBsZWFzdCAkeyhnYXNQcmljZSAvIHdlaVRvR3dlaSkudG9TdHJpbmcoKX1gICtcbiAgICAgICAgICBgIEd3ZWkgdG8gcGVyZm9ybSByZWNvdmVyaWVzLiBUcnkgc2VuZGluZyBzb21lIGZ1bmRzIHRvIHRoaXMgYWRkcmVzcyB0aGVuIHJldHJ5LmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gZ2V0IGJhbGFuY2Ugb2Ygc2VuZGVyIGFkZHJlc3NcbiAgICBpZiAoIXVzZXJBZGRyZXNzRGV0YWlscy5iYWxhbmNlIHx8IHVzZXJBZGRyZXNzRGV0YWlscy5iYWxhbmNlID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGZ1bmRzIHRvIHJlY292ZXIgZnJvbSBzb3VyY2UgYWRkcmVzcycpO1xuICAgIH1cbiAgICBjb25zdCB0eEFtb3VudCA9IHVzZXJBZGRyZXNzRGV0YWlscy5iYWxhbmNlO1xuICAgIGlmIChuZXcgQmlnTnVtYmVyKHR4QW1vdW50KS5pc0xlc3NUaGFuT3JFcXVhbFRvKDApKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dhbGxldCBkb2VzIG5vdCBoYXZlIGVub3VnaCBmdW5kcyB0byByZWNvdmVyJyk7XG4gICAgfVxuXG4gICAgY29uc3QgZmVlSW5mbyA9IHtcbiAgICAgIGZlZTogbmV3IEJpZ051bWJlcihUUkFOU0FDVElPTl9GRUUuVFJBTlNGRVIpLFxuICAgICAgZ2FzTGltaXQ6IG5ldyBCaWdOdW1iZXIoZ2FzTGltaXQpLFxuICAgICAgc3RvcmFnZUxpbWl0OiBuZXcgQmlnTnVtYmVyKFRSQU5TQUNUSU9OX1NUT1JBR0VfTElNSVQuVFJBTlNGRVIpLFxuICAgIH07XG5cbiAgICBjb25zdCB0eEJ1aWxkZXIgPSBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyKGNvaW5zLmdldCh0aGlzLmdldENoYWluKCkpKTtcblxuICAgIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICB0eEJ1aWxkZXIuc291cmNlKGJhY2t1cEtleUFkZHJlc3MpO1xuXG4gICAgLy8gVXNlZCB0byBzZXQgdGhlIGJyYW5jaCBmb3IgdGhlIHRyYW5zYWN0aW9uXG4gICAgY29uc3QgY2hhaW5IZWFkOiBhbnkgPSBhd2FpdCB0aGlzLnJlY292ZXJ5QmxvY2tjaGFpbkV4cGxvcmVyUXVlcnkoe1xuICAgICAgYWN0aW9uUGF0aDogJ2hlYWQnLFxuICAgIH0pO1xuXG4gICAgaWYgKCFjaGFpbkhlYWQgfHwgIWNoYWluSGVhZC5oYXNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBmZXRjaCBjaGFpbiBoZWFkJyk7XG4gICAgfVxuICAgIHR4QnVpbGRlci5icmFuY2goY2hhaW5IZWFkLmhhc2gpO1xuXG4gICAgaWYgKCFiYWNrdXBBZGRyZXNzRGV0YWlscy5yZXZlYWxlZCkge1xuICAgICAgZmVlSW5mby5mZWUgPSBmZWVJbmZvLmZlZS5wbHVzKFRSQU5TQUNUSU9OX0ZFRS5SRVZFQUwpO1xuICAgICAgZmVlSW5mby5nYXNMaW1pdCA9IGZlZUluZm8uZ2FzTGltaXQucGx1cyhUUkFOU0FDVElPTl9HQVNfTElNSVQuUkVWRUFMKTtcbiAgICAgIGZlZUluZm8uc3RvcmFnZUxpbWl0ID0gZmVlSW5mby5zdG9yYWdlTGltaXQucGx1cyhUUkFOU0FDVElPTl9TVE9SQUdFX0xJTUlULlJFVkVBTCk7XG4gICAgICBiYWNrdXBLZXlOb25jZS5wbHVzKDEpO1xuICAgICAgY29uc3QgcHVibGljS2V5VG9SZXZlYWwgPSBrZXlQYWlyLmdldEtleXMoKTtcbiAgICAgIHR4QnVpbGRlci5wdWJsaWNLZXlUb1JldmVhbChwdWJsaWNLZXlUb1JldmVhbC5wdWIpO1xuICAgIH1cblxuICAgIHR4QnVpbGRlci5jb3VudGVyKGJhY2t1cEtleU5vbmNlLnRvU3RyaW5nKCkpO1xuXG4gICAgY29uc3QgcGFja2VkRGF0YVRvU2lnbiA9IGF3YWl0IHRoaXMucGFja0RhdGFUb1NpZ24oXG4gICAgICBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzLFxuICAgICAgYmFja3VwS2V5Tm9uY2UudG9TdHJpbmcoKSxcbiAgICAgIHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgdHhBbW91bnQ/LnRvU3RyaW5nKClcbiAgICApO1xuXG4gICAgdHhCdWlsZGVyXG4gICAgICAudHJhbnNmZXIodHhBbW91bnQ/LnRvU3RyaW5nKCkpXG4gICAgICAuZnJvbShwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzKVxuICAgICAgLnRvKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKVxuICAgICAgLmNvdW50ZXIoYmFja3VwS2V5Tm9uY2UudG9TdHJpbmcoKSlcbiAgICAgIC5mZWUoVFJBTlNBQ1RJT05fRkVFLlRSQU5TRkVSLnRvU3RyaW5nKCkpXG4gICAgICAuc3RvcmFnZUxpbWl0KFRSQU5TQUNUSU9OX1NUT1JBR0VfTElNSVQuVFJBTlNGRVIudG9TdHJpbmcoKSlcbiAgICAgIC5nYXNMaW1pdChnYXNMaW1pdC50b1N0cmluZygpKVxuICAgICAgLmRhdGFUb1NpZ24ocGFja2VkRGF0YVRvU2lnbik7XG5cbiAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdHhJbmZvID0gdHgudG9Kc29uKCk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR4SGV4OiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpLFxuICAgICAgICB0eEluZm8sXG4gICAgICAgIHNvdXJjZTogcGFyYW1zLndhbGxldENvbnRyYWN0QWRkcmVzcyxcbiAgICAgICAgZGF0YVRvU2lnbjogcGFja2VkRGF0YVRvU2lnbixcbiAgICAgICAgZmVlSW5mbyxcbiAgICAgICAgc291cmNlQ291bnRlcjogYmFja3VwS2V5Tm9uY2UudG9TdHJpbmcoKSxcbiAgICAgICAgdHJhbnNmZXJDb3VudGVyczogW2JhY2t1cEtleU5vbmNlLnRvU3RyaW5nKCldLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogYmFja3VwU2lnbmluZ0tleSB9KTtcbiAgICBjb25zdCBzaWduZWRUeCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiBzaWduZWRUeC5pZCxcbiAgICAgIHR4OiBzaWduZWRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRXhwbGFpbiBhIFRlem9zIHRyYW5zYWN0aW9uIGZyb20gdHhIZXhcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKi9cbiAgYXN5bmMgZXhwbGFpblRyYW5zYWN0aW9uKHBhcmFtczogSW50ZXJmYWNlLkV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFRyYW5zYWN0aW9uRXhwbGFuYXRpb24+IHtcbiAgICBjb25zdCB0eEhleCA9IHBhcmFtcy50eEhleCB8fCAocGFyYW1zLmhhbGZTaWduZWQgJiYgcGFyYW1zLmhhbGZTaWduZWQudHhIZXgpO1xuICAgIGlmICghdHhIZXggfHwgIXBhcmFtcy5mZWVJbmZvKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgZXhwbGFpbiB0eCBwYXJhbWV0ZXJzJyk7XG4gICAgfVxuICAgIGNvbnN0IHR4QnVpbGRlciA9IG5ldyBUcmFuc2FjdGlvbkJ1aWxkZXIoY29pbnMuZ2V0KHRoaXMuZ2V0Q2hhaW4oKSkpO1xuICAgIC8vIE5ld2VyIGNvaW5zIGNhbiByZXR1cm4gQmFzZVRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkgaW5zdGVhZCBvZiBCYXNlVHJhbnNhY3Rpb25CdWlsZGVyXG4gICAgaWYgKCEodHhCdWlsZGVyIGluc3RhbmNlb2YgQmFzZVRyYW5zYWN0aW9uQnVpbGRlcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2V0QnVpbGRlcigpIGRpZCBub3QgcmV0dXJuIGFuIEJhc2VUcmFuc2FjdGlvbkJ1aWxkZXIgb2JqZWN0LiBIYXMgaXQgYmVlbiB1cGRhdGVkPycpO1xuICAgIH1cbiAgICB0eEJ1aWxkZXIuZnJvbSh0eEhleCk7XG4gICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcblxuICAgIGNvbnN0IGRpc3BsYXlPcmRlciA9IFsnaWQnLCAnb3V0cHV0QW1vdW50JywgJ2NoYW5nZUFtb3VudCcsICdvdXRwdXRzJywgJ2NoYW5nZU91dHB1dHMnLCAnZmVlJ107XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGlzcGxheU9yZGVyLFxuICAgICAgaWQ6IHR4LmlkLFxuICAgICAgb3V0cHV0czogdHgub3V0cHV0cyxcbiAgICAgIG91dHB1dEFtb3VudDogdHgub3V0cHV0c1xuICAgICAgICAucmVkdWNlKChhY2N1bXVsYXRvciwgb3V0cHV0KSA9PiBhY2N1bXVsYXRvci5wbHVzKG91dHB1dC52YWx1ZSksIG5ldyBCaWdOdW1iZXIoJzAnKSlcbiAgICAgICAgLnRvRml4ZWQoMCksXG4gICAgICBjaGFuZ2VPdXRwdXRzOiBbXSwgLy8gYWNjb3VudCBiYXNlZCBkb2VzIG5vdCB1c2UgY2hhbmdlIG91dHB1dHNcbiAgICAgIGNoYW5nZUFtb3VudDogJzAnLCAvLyBhY2NvdW50IGJhc2UgZG9lcyBub3QgbWFrZSBjaGFuZ2VcbiAgICAgIGZlZTogcGFyYW1zLmZlZUluZm8sXG4gICAgfSBhcyBhbnk7XG4gIH1cblxuICBpc1ZhbGlkUHViKHB1Yjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIFV0aWxzLmlzVmFsaWRQdWJsaWNLZXkocHViKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBhdWRpdERlY3J5cHRlZEtleShwYXJhbXM6IEF1ZGl0RGVjcnlwdGVkS2V5UGFyYW1zKSB7XG4gICAgdGhyb3cgbmV3IE1ldGhvZE5vdEltcGxlbWVudGVkRXJyb3IoKTtcbiAgfVxufVxuIl19