@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.
- package/CHANGELOG.md +6 -0
- package/package.json +8 -8
- package/dist/src/index.d.ts +0 -5
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -44
- package/dist/src/lib/address.d.ts +0 -8
- package/dist/src/lib/address.d.ts.map +0 -1
- package/dist/src/lib/address.js +0 -10
- package/dist/src/lib/iface.d.ts +0 -148
- package/dist/src/lib/iface.d.ts.map +0 -1
- package/dist/src/lib/iface.js +0 -3
- package/dist/src/lib/index.d.ts +0 -10
- package/dist/src/lib/index.d.ts.map +0 -1
- package/dist/src/lib/index.js +0 -51
- package/dist/src/lib/keyPair.d.ts +0 -40
- package/dist/src/lib/keyPair.d.ts.map +0 -1
- package/dist/src/lib/keyPair.js +0 -149
- package/dist/src/lib/multisigUtils.d.ts +0 -134
- package/dist/src/lib/multisigUtils.d.ts.map +0 -1
- package/dist/src/lib/multisigUtils.js +0 -1193
- package/dist/src/lib/transaction.d.ts +0 -119
- package/dist/src/lib/transaction.d.ts.map +0 -1
- package/dist/src/lib/transaction.js +0 -329
- package/dist/src/lib/transactionBuilder.d.ts +0 -171
- package/dist/src/lib/transactionBuilder.d.ts.map +0 -1
- package/dist/src/lib/transactionBuilder.js +0 -453
- package/dist/src/lib/transferBuilder.d.ts +0 -24
- package/dist/src/lib/transferBuilder.d.ts.map +0 -1
- package/dist/src/lib/transferBuilder.js +0 -64
- package/dist/src/lib/utils.d.ts +0 -280
- package/dist/src/lib/utils.d.ts.map +0 -1
- package/dist/src/lib/utils.js +0 -492
- package/dist/src/register.d.ts +0 -3
- package/dist/src/register.d.ts.map +0 -1
- package/dist/src/register.js +0 -11
- package/dist/src/txtz.d.ts +0 -13
- package/dist/src/txtz.d.ts.map +0 -1
- package/dist/src/txtz.js +0 -14
- package/dist/src/xtz.d.ts +0 -125
- package/dist/src/xtz.d.ts.map +0 -1
- 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
|
package/dist/src/xtz.d.ts.map
DELETED
|
@@ -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
|