@bitgo/abstract-utxo 1.0.1-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +5 -0
- package/CHANGELOG.md +11 -0
- package/LICENSE +191 -0
- package/README.md +1 -0
- package/dist/src/abstractUtxoCoin.d.ts +388 -0
- package/dist/src/abstractUtxoCoin.d.ts.map +1 -0
- package/dist/src/abstractUtxoCoin.js +955 -0
- package/dist/src/config.d.ts +7 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +12 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +18 -0
- package/dist/src/parseOutput.d.ts +22 -0
- package/dist/src/parseOutput.d.ts.map +1 -0
- package/dist/src/parseOutput.js +169 -0
- package/dist/src/recovery/RecoveryProvider.d.ts +18 -0
- package/dist/src/recovery/RecoveryProvider.d.ts.map +1 -0
- package/dist/src/recovery/RecoveryProvider.js +23 -0
- package/dist/src/recovery/backupKeyRecovery.d.ts +56 -0
- package/dist/src/recovery/backupKeyRecovery.d.ts.map +1 -0
- package/dist/src/recovery/backupKeyRecovery.js +273 -0
- package/dist/src/recovery/baseApi.d.ts +27 -0
- package/dist/src/recovery/baseApi.d.ts.map +1 -0
- package/dist/src/recovery/baseApi.js +73 -0
- package/dist/src/recovery/coingeckoApi.d.ts +9 -0
- package/dist/src/recovery/coingeckoApi.d.ts.map +1 -0
- package/dist/src/recovery/coingeckoApi.js +47 -0
- package/dist/src/recovery/crossChainRecovery.d.ts +95 -0
- package/dist/src/recovery/crossChainRecovery.d.ts.map +1 -0
- package/dist/src/recovery/crossChainRecovery.js +318 -0
- package/dist/src/recovery/index.d.ts +8 -0
- package/dist/src/recovery/index.d.ts.map +1 -0
- package/dist/src/recovery/index.js +20 -0
- package/dist/src/recovery/mempoolApi.d.ts +7 -0
- package/dist/src/recovery/mempoolApi.d.ts.map +1 -0
- package/dist/src/recovery/mempoolApi.js +33 -0
- package/dist/src/recovery/smartbitApi.d.ts +11 -0
- package/dist/src/recovery/smartbitApi.d.ts.map +1 -0
- package/dist/src/recovery/smartbitApi.js +36 -0
- package/dist/src/replayProtection.d.ts +5 -0
- package/dist/src/replayProtection.d.ts.map +1 -0
- package/dist/src/replayProtection.js +21 -0
- package/dist/src/sign.d.ts +29 -0
- package/dist/src/sign.d.ts.map +1 -0
- package/dist/src/sign.js +104 -0
- package/dist/tsconfig.tsbuildinfo +7371 -0
- package/package.json +55 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @prettier
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.backupKeyRecovery = void 0;
|
|
7
|
+
const _ = require("lodash");
|
|
8
|
+
const utxolib = require("@bitgo/utxo-lib");
|
|
9
|
+
const bitgo_1 = require("@bitgo/utxo-lib/dist/src/bitgo");
|
|
10
|
+
const unspents_1 = require("@bitgo/unspents");
|
|
11
|
+
const sdk_core_1 = require("@bitgo/sdk-core");
|
|
12
|
+
const RecoveryProvider_1 = require("./RecoveryProvider");
|
|
13
|
+
const baseApi_1 = require("./baseApi");
|
|
14
|
+
const smartbitApi_1 = require("./smartbitApi");
|
|
15
|
+
const mempoolApi_1 = require("./mempoolApi");
|
|
16
|
+
const coingeckoApi_1 = require("./coingeckoApi");
|
|
17
|
+
const sign_1 = require("../sign");
|
|
18
|
+
/**
|
|
19
|
+
* This transforms the txInfo from recover into the format that offline-signing-tool expects
|
|
20
|
+
* @param coinName
|
|
21
|
+
* @param txInfo
|
|
22
|
+
* @param txHex
|
|
23
|
+
* @returns {{txHex: *, txInfo: {unspents: *}, feeInfo: {}, coin: void}}
|
|
24
|
+
*/
|
|
25
|
+
function formatForOfflineVault(coinName, txInfo, txHex) {
|
|
26
|
+
return {
|
|
27
|
+
txHex,
|
|
28
|
+
txInfo: {
|
|
29
|
+
unspents: txInfo.inputs,
|
|
30
|
+
},
|
|
31
|
+
feeInfo: {},
|
|
32
|
+
coin: coinName,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get the current market price from a third party to be used for recovery
|
|
37
|
+
* This function is only intended for non-bitgo recovery transactions, when it is necessary
|
|
38
|
+
* to calculate the rough fee needed to pay to Keyternal. We are okay with approximating,
|
|
39
|
+
* because the resulting price of this function only has less than 1 dollar influence on the
|
|
40
|
+
* fee that needs to be paid to Keyternal.
|
|
41
|
+
*
|
|
42
|
+
* See calculateFeeAmount function: return Math.round(feeAmountUsd / currentPrice * self.getBaseFactor());
|
|
43
|
+
*
|
|
44
|
+
* This end function should not be used as an accurate endpoint, since some coins' prices are missing from the provider
|
|
45
|
+
*/
|
|
46
|
+
async function getRecoveryMarketPrice(coin) {
|
|
47
|
+
return await new coingeckoApi_1.CoingeckoApi().getUSDPrice(coin.getFamily());
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Calculates the amount (in base units) to pay a KRS provider when building a recovery transaction
|
|
51
|
+
* @param coin
|
|
52
|
+
* @param params
|
|
53
|
+
* @param params.provider {String} the KRS provider that holds the backup key
|
|
54
|
+
* @param params.amount {Number} amount (in base units) to be recovered
|
|
55
|
+
* @returns {*}
|
|
56
|
+
*/
|
|
57
|
+
async function calculateFeeAmount(coin, params) {
|
|
58
|
+
const krsProvider = sdk_core_1.krsProviders[params.provider];
|
|
59
|
+
if (krsProvider === undefined) {
|
|
60
|
+
throw new Error(`no fee structure specified for provider ${params.provider}`);
|
|
61
|
+
}
|
|
62
|
+
if (krsProvider.feeType === 'flatUsd') {
|
|
63
|
+
const feeAmountUsd = krsProvider.feeAmount;
|
|
64
|
+
const currentPrice = await getRecoveryMarketPrice(coin);
|
|
65
|
+
return Math.round((feeAmountUsd / currentPrice) * coin.getBaseFactor());
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// we can add more fee structures here as needed for different providers, such as percentage of recovery amount
|
|
69
|
+
throw new Error('Fee structure not implemented');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function queryBlockchainUnspentsPath(coin, params, walletKeys, chain) {
|
|
73
|
+
var _a;
|
|
74
|
+
const recoveryProvider = (_a = params.recoveryProvider) !== null && _a !== void 0 ? _a : RecoveryProvider_1.forCoin(coin.getChain(), params.apiKey);
|
|
75
|
+
const MAX_SEQUENTIAL_ADDRESSES_WITHOUT_TXS = params.scan || 20;
|
|
76
|
+
let numSequentialAddressesWithoutTxs = 0;
|
|
77
|
+
async function gatherUnspents(addrIndex) {
|
|
78
|
+
const walletKeysForUnspent = walletKeys.deriveForChainAndIndex(chain, addrIndex);
|
|
79
|
+
const address = coin.createMultiSigAddress(bitgo_1.scriptTypeForChain(chain), 2, walletKeysForUnspent.publicKeys);
|
|
80
|
+
const addrInfo = await recoveryProvider.getAddressInfo(address.address);
|
|
81
|
+
// we use txCount here because it implies usage - having tx'es means the addr was generated and used
|
|
82
|
+
if (addrInfo.txCount === 0) {
|
|
83
|
+
numSequentialAddressesWithoutTxs++;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
numSequentialAddressesWithoutTxs = 0;
|
|
87
|
+
if (addrInfo.balance > 0) {
|
|
88
|
+
console.log(`Found an address with balance: ${address.address} with balance ${addrInfo.balance}`);
|
|
89
|
+
const addressUnspents = await recoveryProvider.getUnspentsForAddresses([address.address]);
|
|
90
|
+
walletUnspents.push(...addressUnspents.map((u) => ({
|
|
91
|
+
...u,
|
|
92
|
+
chain: chain,
|
|
93
|
+
index: addrIndex,
|
|
94
|
+
})));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (numSequentialAddressesWithoutTxs >= MAX_SEQUENTIAL_ADDRESSES_WITHOUT_TXS) {
|
|
98
|
+
// stop searching for addresses with unspents in them, we've found ${MAX_SEQUENTIAL_ADDRESSES_WITHOUT_TXS} in a row with none
|
|
99
|
+
// we are done
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
return gatherUnspents(addrIndex + 1);
|
|
103
|
+
}
|
|
104
|
+
// get unspents for these addresses
|
|
105
|
+
const walletUnspents = [];
|
|
106
|
+
// This will populate walletAddresses
|
|
107
|
+
await gatherUnspents(0);
|
|
108
|
+
if (walletUnspents.length === 0) {
|
|
109
|
+
// Couldn't find any addresses with funds
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
return walletUnspents;
|
|
113
|
+
}
|
|
114
|
+
async function getRecoveryFeePerBytes(coin, { defaultValue }) {
|
|
115
|
+
try {
|
|
116
|
+
return await mempoolApi_1.MempoolApi.forCoin(coin.getChain()).getRecoveryFeePerBytes();
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
console.dir(e);
|
|
120
|
+
return defaultValue;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Builds a funds recovery transaction without BitGo
|
|
125
|
+
* @param coin
|
|
126
|
+
* @param bitgo
|
|
127
|
+
* @param params
|
|
128
|
+
* - userKey: [encrypted] xprv, or xpub
|
|
129
|
+
* - backupKey: [encrypted] xprv, or xpub if the xprv is held by a KRS provider
|
|
130
|
+
* - walletPassphrase: necessary if one of the xprvs is encrypted
|
|
131
|
+
* - bitgoKey: xpub
|
|
132
|
+
* - krsProvider: necessary if backup key is held by KRS
|
|
133
|
+
* - recoveryDestination: target address to send recovered funds to
|
|
134
|
+
* - scan: the amount of consecutive addresses without unspents to scan through before stopping
|
|
135
|
+
* - ignoreAddressTypes: (optional) scripts to ignore
|
|
136
|
+
* for example: ['p2shP2wsh', 'p2wsh'] will prevent code from checking for wrapped-segwit and native-segwit chains on the public block explorers
|
|
137
|
+
*/
|
|
138
|
+
async function backupKeyRecovery(coin, bitgo, params) {
|
|
139
|
+
if (_.isUndefined(params.userKey)) {
|
|
140
|
+
throw new Error('missing userKey');
|
|
141
|
+
}
|
|
142
|
+
if (_.isUndefined(params.backupKey)) {
|
|
143
|
+
throw new Error('missing backupKey');
|
|
144
|
+
}
|
|
145
|
+
if (_.isUndefined(params.recoveryDestination) || !coin.isValidAddress(params.recoveryDestination)) {
|
|
146
|
+
throw new Error('invalid recoveryDestination');
|
|
147
|
+
}
|
|
148
|
+
if (!_.isUndefined(params.scan) && (!_.isInteger(params.scan) || params.scan < 0)) {
|
|
149
|
+
throw new Error('scan must be a positive integer');
|
|
150
|
+
}
|
|
151
|
+
const isKrsRecovery = sdk_core_1.getIsKrsRecovery(params);
|
|
152
|
+
const isUnsignedSweep = sdk_core_1.getIsUnsignedSweep(params);
|
|
153
|
+
const krsProvider = isKrsRecovery ? sdk_core_1.getKrsProvider(coin, params.krsProvider) : undefined;
|
|
154
|
+
// check whether key material and password authenticate the users and return parent keys of all three keys of the wallet
|
|
155
|
+
const keys = sdk_core_1.getBip32Keys(bitgo, params, { requireBitGoXpub: true });
|
|
156
|
+
if (!sdk_core_1.isTriple(keys)) {
|
|
157
|
+
throw new Error(`expected key triple`);
|
|
158
|
+
}
|
|
159
|
+
const walletKeys = new bitgo_1.RootWalletKeys(keys, [
|
|
160
|
+
params.userKeyPath || bitgo_1.RootWalletKeys.defaultPrefix,
|
|
161
|
+
bitgo_1.RootWalletKeys.defaultPrefix,
|
|
162
|
+
bitgo_1.RootWalletKeys.defaultPrefix,
|
|
163
|
+
]);
|
|
164
|
+
const unspents = (await Promise.all(bitgo_1.outputScripts.scriptTypes2Of3
|
|
165
|
+
.filter((addressType) => { var _a; return coin.supportsAddressType(addressType) && !((_a = params.ignoreAddressTypes) === null || _a === void 0 ? void 0 : _a.includes(addressType)); })
|
|
166
|
+
.reduce((queries, addressType) => [
|
|
167
|
+
...queries,
|
|
168
|
+
queryBlockchainUnspentsPath(coin, params, walletKeys, bitgo_1.getExternalChainCode(addressType)),
|
|
169
|
+
queryBlockchainUnspentsPath(coin, params, walletKeys, bitgo_1.getInternalChainCode(addressType)),
|
|
170
|
+
], []))).flat();
|
|
171
|
+
// Execute the queries and gather the unspents
|
|
172
|
+
const totalInputAmount = unspents.reduce((sum, u) => sum + u.value, 0);
|
|
173
|
+
if (totalInputAmount <= 0) {
|
|
174
|
+
throw new sdk_core_1.ErrorNoInputToRecover();
|
|
175
|
+
}
|
|
176
|
+
// Build the transaction
|
|
177
|
+
const transactionBuilder = utxolib.bitgo.createTransactionBuilderForNetwork(coin.network);
|
|
178
|
+
const txInfo = {};
|
|
179
|
+
const feePerByte = await getRecoveryFeePerBytes(coin, { defaultValue: 100 });
|
|
180
|
+
// KRS recovery transactions have a 2nd output to pay the recovery fee, like paygo fees. Use p2wsh outputs because
|
|
181
|
+
// they are the largest outputs and thus the most conservative estimate to use in calculating fees. Also use
|
|
182
|
+
// segwit overhead size and p2sh inputs for the same reason.
|
|
183
|
+
const outputSize = (isKrsRecovery ? 2 : 1) * unspents_1.VirtualSizes.txP2wshOutputSize;
|
|
184
|
+
const approximateSize = unspents_1.VirtualSizes.txSegOverheadVSize + outputSize + unspents_1.VirtualSizes.txP2shInputSize * unspents.length;
|
|
185
|
+
const approximateFee = approximateSize * feePerByte;
|
|
186
|
+
// Construct a transaction
|
|
187
|
+
txInfo.inputs = unspents;
|
|
188
|
+
unspents.forEach((unspent) => {
|
|
189
|
+
const { txid, vout } = bitgo_1.parseOutputId(unspent.id);
|
|
190
|
+
transactionBuilder.addInput(txid, vout, 0xffffffff, utxolib.address.toOutputScript(unspent.address, coin.network), unspent.value);
|
|
191
|
+
});
|
|
192
|
+
let recoveryAmount = totalInputAmount - approximateFee;
|
|
193
|
+
let krsFee;
|
|
194
|
+
if (isKrsRecovery && params.krsProvider) {
|
|
195
|
+
try {
|
|
196
|
+
krsFee = await calculateFeeAmount(coin, {
|
|
197
|
+
provider: params.krsProvider,
|
|
198
|
+
amount: recoveryAmount,
|
|
199
|
+
});
|
|
200
|
+
recoveryAmount -= krsFee;
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
// Don't let this error block the recovery -
|
|
204
|
+
console.dir(err);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (recoveryAmount < 0) {
|
|
208
|
+
throw new Error(`this wallet\'s balance is too low to pay the fees specified by the KRS provider.
|
|
209
|
+
Existing balance on wallet: ${totalInputAmount}. Estimated network fee for the recovery transaction
|
|
210
|
+
: ${approximateFee}, KRS fee to pay: ${krsFee}. After deducting fees, your total recoverable balance
|
|
211
|
+
is ${recoveryAmount}`);
|
|
212
|
+
}
|
|
213
|
+
transactionBuilder.addOutput(params.recoveryDestination, recoveryAmount);
|
|
214
|
+
if (krsProvider && krsFee > 0) {
|
|
215
|
+
if (!krsProvider.feeAddresses) {
|
|
216
|
+
throw new Error(`keyProvider must define feeAddresses`);
|
|
217
|
+
}
|
|
218
|
+
const krsFeeAddress = krsProvider.feeAddresses[coin.getChain()];
|
|
219
|
+
if (!krsFeeAddress) {
|
|
220
|
+
throw new Error('this KRS provider has not configured their fee structure yet - recovery cannot be completed');
|
|
221
|
+
}
|
|
222
|
+
transactionBuilder.addOutput(krsFeeAddress, krsFee);
|
|
223
|
+
}
|
|
224
|
+
if (isUnsignedSweep) {
|
|
225
|
+
const txHex = transactionBuilder.buildIncomplete().toBuffer().toString('hex');
|
|
226
|
+
return formatForOfflineVault(coin.getChain(), txInfo, txHex);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
let transaction = sign_1.signAndVerifyWalletTransaction(transactionBuilder, unspents, new bitgo_1.WalletUnspentSigner(walletKeys, walletKeys.user, walletKeys.backup), { isLastSignature: false });
|
|
230
|
+
if (!isKrsRecovery) {
|
|
231
|
+
transaction = sign_1.signAndVerifyWalletTransaction(transaction, unspents, new bitgo_1.WalletUnspentSigner(walletKeys, walletKeys.backup, walletKeys.user), { isLastSignature: true });
|
|
232
|
+
}
|
|
233
|
+
txInfo.transactionHex = transaction.toBuffer().toString('hex');
|
|
234
|
+
let transactionDetails;
|
|
235
|
+
try {
|
|
236
|
+
transactionDetails = await smartbitApi_1.SmartbitApi.forCoin(coin.getChain()).getTransactionDetails(transaction);
|
|
237
|
+
}
|
|
238
|
+
catch (e) {
|
|
239
|
+
// some coins don't have a reliable third party verification endpoint, or sometimes the third party endpoint
|
|
240
|
+
// could be unavailable due to service outage, so we continue without verification for those coins, but we will
|
|
241
|
+
// let users know that they should verify their own
|
|
242
|
+
// this message should be piped to WRW and displayed on the UI
|
|
243
|
+
if (e instanceof baseApi_1.ApiNotImplementedError || e instanceof baseApi_1.ApiRequestError) {
|
|
244
|
+
console.log('Please verify your transaction by decoding the tx hex using a third-party api of your choice');
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
throw e;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (transactionDetails) {
|
|
251
|
+
/**
|
|
252
|
+
* Verify that the txhex user signs correspond to the correct tx they intended
|
|
253
|
+
* by 1) getting back the decoded transaction based on the txhex
|
|
254
|
+
* and then 2) compute the txid (hash), h1 of the decoded transaction 3) compare h1
|
|
255
|
+
* to the txid (hash) of the transaction (including unspent info) we constructed
|
|
256
|
+
*/
|
|
257
|
+
if (transactionDetails.TxId !== transaction.getId()) {
|
|
258
|
+
console.log('txhash/txid returned by blockexplorer: ', transactionDetails.TxId);
|
|
259
|
+
console.log('txhash/txid of the transaction bitgo constructed', transaction.getId());
|
|
260
|
+
throw new Error('inconsistent recovery transaction id');
|
|
261
|
+
}
|
|
262
|
+
txInfo.tx = transactionDetails;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (isKrsRecovery) {
|
|
266
|
+
txInfo.coin = coin.getChain();
|
|
267
|
+
txInfo.backupKey = params.backupKey;
|
|
268
|
+
txInfo.recoveryAmount = recoveryAmount;
|
|
269
|
+
}
|
|
270
|
+
return txInfo;
|
|
271
|
+
}
|
|
272
|
+
exports.backupKeyRecovery = backupKeyRecovery;
|
|
273
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFja3VwS2V5UmVjb3ZlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcmVjb3ZlcnkvYmFja3VwS2V5UmVjb3ZlcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOztHQUVHOzs7QUFFSCw0QkFBNEI7QUFDNUIsMkNBQTJDO0FBQzNDLDBEQVV3QztBQUV4Qyw4Q0FBK0M7QUFFL0MsOENBU3lCO0FBR3pCLHlEQUErRDtBQUMvRCx1Q0FBb0U7QUFDcEUsK0NBQTRDO0FBQzVDLDZDQUEwQztBQUMxQyxpREFBOEM7QUFDOUMsa0NBQXlEO0FBZXpEOzs7Ozs7R0FNRztBQUNILFNBQVMscUJBQXFCLENBQzVCLFFBQWdCLEVBQ2hCLE1BQTBCLEVBQzFCLEtBQWE7SUFFYixPQUFPO1FBQ0wsS0FBSztRQUNMLE1BQU0sRUFBRTtZQUNOLFFBQVEsRUFBRSxNQUFNLENBQUMsTUFBTTtTQUN4QjtRQUNELE9BQU8sRUFBRSxFQUFFO1FBQ1gsSUFBSSxFQUFFLFFBQVE7S0FDZixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxLQUFLLFVBQVUsc0JBQXNCLENBQUMsSUFBc0I7SUFDMUQsT0FBTyxNQUFNLElBQUksMkJBQVksRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztBQUNoRSxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILEtBQUssVUFBVSxrQkFBa0IsQ0FDL0IsSUFBc0IsRUFDdEIsTUFBNkM7SUFFN0MsTUFBTSxXQUFXLEdBQUcsdUJBQVksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFbEQsSUFBSSxXQUFXLEtBQUssU0FBUyxFQUFFO1FBQzdCLE1BQU0sSUFBSSxLQUFLLENBQUMsMkNBQTJDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO0tBQy9FO0lBRUQsSUFBSSxXQUFXLENBQUMsT0FBTyxLQUFLLFNBQVMsRUFBRTtRQUNyQyxN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R0FBK0c7WUFDL0csbURBQW1EO1lBQ25ELDhEQUE4RDtZQUM5RCxJQUFJLENBQUMsWUFBWSxnQ0FBc0IsSUFBSSxDQUFDLFlBQVkseUJBQWUsRUFBRTtnQkFDdkUsT0FBTyxDQUFDLEdBQUcsQ0FBQyw4RkFBOEYsQ0FBQyxDQUFDO2FBQzdHO2lCQUFNO2dCQUNMLE1BQU0sQ0FBQyxDQUFDO2FBQ1Q7U0FDRjtRQUVELElBQUksa0JBQWtCLEVBQUU7WUFDdEI7Ozs7O2VBS0c7WUFDSCxJQUFJLGtCQUFrQixDQUFDLElBQUksS0FBSyxXQUFXLENBQUMsS0FBSyxFQUFFLEVBQUU7Z0JBQ25ELE9BQU8sQ0FBQyxHQUFHLENBQUMseUNBQXlDLEVBQUUsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ2hGLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0RBQWtELEVBQUUsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7Z0JBQ3JGLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQzthQUN6RDtZQUNELE1BQU0sQ0FBQyxFQUFFLEdBQUcsa0JBQWtCLENBQUM7U0FDaEM7S0FDRjtJQUVELElBQUksYUFBYSxFQUFFO1FBQ2pCLE1BQU0sQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQzlCLE1BQU0sQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQztRQUNwQyxNQUFNLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztLQUN4QztJQUVELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUF4TEQsOENBd0xDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuXG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgKiBhcyB1dHhvbGliIGZyb20gJ0BiaXRnby91dHhvLWxpYic7XG5pbXBvcnQge1xuICBDaGFpbkNvZGUsXG4gIGdldEludGVybmFsQ2hhaW5Db2RlLFxuICBwYXJzZU91dHB1dElkLFxuICBSb290V2FsbGV0S2V5cyxcbiAgc2NyaXB0VHlwZUZvckNoYWluLFxuICBXYWxsZXRVbnNwZW50LFxuICBXYWxsZXRVbnNwZW50U2lnbmVyLFxuICBvdXRwdXRTY3JpcHRzLFxuICBnZXRFeHRlcm5hbENoYWluQ29kZSxcbn0gZnJvbSAnQGJpdGdvL3V0eG8tbGliL2Rpc3Qvc3JjL2JpdGdvJztcblxuaW1wb3J0IHsgVmlydHVhbFNpemVzIH0gZnJvbSAnQGJpdGdvL3Vuc3BlbnRzJztcblxuaW1wb3J0IHtcbiAgQml0R29CYXNlLFxuICBFcnJvck5vSW5wdXRUb1JlY292ZXIsXG4gIGdldEtyc1Byb3ZpZGVyLFxuICBnZXRCaXAzMktleXMsXG4gIGdldElzS3JzUmVjb3ZlcnksXG4gIGdldElzVW5zaWduZWRTd2VlcCxcbiAgaXNUcmlwbGUsXG4gIGtyc1Byb3ZpZGVycyxcbn0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7IEFic3RyYWN0VXR4b0NvaW4gfSBmcm9tICcuLi9hYnN0cmFjdFV0eG9Db2luJztcblxuaW1wb3J0IHsgZm9yQ29pbiwgUmVjb3ZlcnlQcm92aWRlciB9IGZyb20gJy4vUmVjb3ZlcnlQcm92aWRlcic7XG5pbXBvcnQgeyBBcGlOb3RJbXBsZW1lbnRlZEVycm9yLCBBcGlSZXF1ZXN0RXJyb3IgfSBmcm9tICcuL2Jhc2VBcGknO1xuaW1wb3J0IHsgU21hcnRiaXRBcGkgfSBmcm9tICcuL3NtYXJ0Yml0QXBpJztcbmltcG9ydCB7IE1lbXBvb2xBcGkgfSBmcm9tICcuL21lbXBvb2xBcGknO1xuaW1wb3J0IHsgQ29pbmdlY2tvQXBpIH0gZnJvbSAnLi9jb2luZ2Vja29BcGknO1xuaW1wb3J0IHsgc2lnbkFuZFZlcmlmeVdhbGxldFRyYW5zYWN0aW9uIH0gZnJvbSAnLi4vc2lnbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT2ZmbGluZVZhdWx0VHhJbmZvIHtcbiAgaW5wdXRzOiBXYWxsZXRVbnNwZW50W107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRm9ybWF0dGVkT2ZmbGluZVZhdWx0VHhJbmZvIHtcbiAgdHhJbmZvOiB7XG4gICAgdW5zcGVudHM6IFdhbGxldFVuc3BlbnRbXTtcbiAgfTtcbiAgdHhIZXg6IHN0cmluZztcbiAgZmVlSW5mbzogUmVjb3JkPHN0cmluZywgbmV2ZXI+O1xuICBjb2luOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhpcyB0cmFuc2Zvcm1zIHRoZSB0eEluZm8gZnJvbSByZWNvdmVyIGludG8gdGhlIGZvcm1hdCB0aGF0IG9mZmxpbmUtc2lnbmluZy10b29sIGV4cGVjdHNcbiAqIEBwYXJhbSBjb2luTmFtZVxuICogQHBhcmFtIHR4SW5mb1xuICogQHBhcmFtIHR4SGV4XG4gKiBAcmV0dXJucyB7e3R4SGV4OiAqLCB0eEluZm86IHt1bnNwZW50czogKn0sIGZlZUluZm86IHt9LCBjb2luOiB2b2lkfX1cbiAqL1xuZnVuY3Rpb24gZm9ybWF0Rm9yT2ZmbGluZVZhdWx0KFxuICBjb2luTmFtZTogc3RyaW5nLFxuICB0eEluZm86IE9mZmxpbmVWYXVsdFR4SW5mbyxcbiAgdHhIZXg6IHN0cmluZ1xuKTogRm9ybWF0dGVkT2ZmbGluZVZhdWx0VHhJbmZvIHtcbiAgcmV0dXJuIHtcbiAgICB0eEhleCxcbiAgICB0eEluZm86IHtcbiAgICAgIHVuc3BlbnRzOiB0eEluZm8uaW5wdXRzLFxuICAgIH0sXG4gICAgZmVlSW5mbzoge30sXG4gICAgY29pbjogY29pbk5hbWUsXG4gIH07XG59XG5cbi8qKlxuICogR2V0IHRoZSBjdXJyZW50IG1hcmtldCBwcmljZSBmcm9tIGEgdGhpcmQgcGFydHkgdG8gYmUgdXNlZCBmb3IgcmVjb3ZlcnlcbiAqIFRoaXMgZnVuY3Rpb24gaXMgb25seSBpbnRlbmRlZCBmb3Igbm9uLWJpdGdvIHJlY292ZXJ5IHRyYW5zYWN0aW9ucywgd2hlbiBpdCBpcyBuZWNlc3NhcnlcbiAqIHRvIGNhbGN1bGF0ZSB0aGUgcm91Z2ggZmVlIG5lZWRlZCB0byBwYXkgdG8gS2V5dGVybmFsLiBXZSBhcmUgb2theSB3aXRoIGFwcHJveGltYXRpbmcsXG4gKiBiZWNhdXNlIHRoZSByZXN1bHRpbmcgcHJpY2Ugb2YgdGhpcyBmdW5jdGlvbiBvbmx5IGhhcyBsZXNzIHRoYW4gMSBkb2xsYXIgaW5mbHVlbmNlIG9uIHRoZVxuICogZmVlIHRoYXQgbmVlZHMgdG8gYmUgcGFpZCB0byBLZXl0ZXJuYWwuXG4gKlxuICogU2VlIGNhbGN1bGF0ZUZlZUFtb3VudCBmdW5jdGlvbjogIHJldHVybiBNYXRoLnJvdW5kKGZlZUFtb3VudFVzZCAvIGN1cnJlbnRQcmljZSAqIHNlbGYuZ2V0QmFzZUZhY3RvcigpKTtcbiAqXG4gKiBUaGlzIGVuZCBmdW5jdGlvbiBzaG91bGQgbm90IGJlIHVzZWQgYXMgYW4gYWNjdXJhdGUgZW5kcG9pbnQsIHNpbmNlIHNvbWUgY29pbnMnIHByaWNlcyBhcmUgbWlzc2luZyBmcm9tIHRoZSBwcm92aWRlclxuICovXG5hc3luYyBmdW5jdGlvbiBnZXRSZWNvdmVyeU1hcmtldFByaWNlKGNvaW46IEFic3RyYWN0VXR4b0NvaW4pOiBQcm9taXNlPG51bWJlcj4ge1xuICByZXR1cm4gYXdhaXQgbmV3IENvaW5nZWNrb0FwaSgpLmdldFVTRFByaWNlKGNvaW4uZ2V0RmFtaWx5KCkpO1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGFtb3VudCAoaW4gYmFzZSB1bml0cykgdG8gcGF5IGEgS1JTIHByb3ZpZGVyIHdoZW4gYnVpbGRpbmcgYSByZWNvdmVyeSB0cmFuc2FjdGlvblxuICogQHBhcmFtIGNvaW5cbiAqIEBwYXJhbSBwYXJhbXNcbiAqIEBwYXJhbSBwYXJhbXMucHJvdmlkZXIge1N0cmluZ30gdGhlIEtSUyBwcm92aWRlciB0aGF0IGhvbGRzIHRoZSBiYWNrdXAga2V5XG4gKiBAcGFyYW0gcGFyYW1zLmFtb3VudCB7TnVtYmVyfSBhbW91bnQgKGluIGJhc2UgdW5pdHMpIHRvIGJlIHJlY292ZXJlZFxuICogQHJldHVybnMgeyp9XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNhbGN1bGF0ZUZlZUFtb3VudChcbiAgY29pbjogQWJzdHJhY3RVdHhvQ29pbixcbiAgcGFyYW1zOiB7IHByb3ZpZGVyOiBzdHJpbmc7IGFtb3VudD86IG51bWJlciB9XG4pOiBQcm9taXNlPG51bWJlcj4ge1xuICBjb25zdCBrcnNQcm92aWRlciA9IGtyc1Byb3ZpZGVyc1twYXJhbXMucHJvdmlkZXJdO1xuXG4gIGlmIChrcnNQcm92aWRlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBubyBmZWUgc3RydWN0dXJlIHNwZWNpZmllZCBmb3IgcHJvdmlkZXIgJHtwYXJhbXMucHJvdmlkZXJ9YCk7XG4gIH1cblxuICBpZiAoa3JzUHJvdmlkZXIuZmVlVHlwZSA9PT0gJ2ZsYXRVc2QnKSB7XG4gICAgY29uc3QgZmVlQW1vdW50VXNkID0ga3JzUHJvdmlkZXIuZmVlQW1vdW50O1xuICAgIGNvbnN0IGN1cnJlbnRQcmljZTogbnVtYmVyID0gYXdhaXQgZ2V0UmVjb3ZlcnlNYXJrZXRQcmljZShjb2luKTtcblxuICAgIHJldHVybiBNYXRoLnJvdW5kKChmZWVBbW91bnRVc2QgLyBjdXJyZW50UHJpY2UpICogY29pbi5nZXRCYXNlRmFjdG9yKCkpO1xuICB9IGVsc2Uge1xuICAgIC8vIHdlIGNhbiBhZGQgbW9yZSBmZWUgc3RydWN0dXJlcyBoZXJlIGFzIG5lZWRlZCBmb3IgZGlmZmVyZW50IHByb3ZpZGVycywgc3VjaCBhcyBwZXJjZW50YWdlIG9mIHJlY292ZXJ5IGFtb3VudFxuICAgIHRocm93IG5ldyBFcnJvcignRmVlIHN0cnVjdHVyZSBub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY292ZXJQYXJhbXMge1xuICBzY2FuPzogbnVtYmVyO1xuICB1c2VyS2V5OiBzdHJpbmc7XG4gIGJhY2t1cEtleTogc3RyaW5nO1xuICBiaXRnb0tleTogc3RyaW5nO1xuICByZWNvdmVyeURlc3RpbmF0aW9uOiBzdHJpbmc7XG4gIGtyc1Byb3ZpZGVyPzogc3RyaW5nO1xuICBpZ25vcmVBZGRyZXNzVHlwZXM6IG91dHB1dFNjcmlwdHMuU2NyaXB0VHlwZTJPZjNbXTtcbiAgd2FsbGV0UGFzc3BocmFzZT86IHN0cmluZztcbiAgYXBpS2V5Pzogc3RyaW5nO1xuICB1c2VyS2V5UGF0aD86IHN0cmluZztcbiAgcmVjb3ZlcnlQcm92aWRlcj86IFJlY292ZXJ5UHJvdmlkZXI7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHF1ZXJ5QmxvY2tjaGFpblVuc3BlbnRzUGF0aChcbiAgY29pbjogQWJzdHJhY3RVdHhvQ29pbixcbiAgcGFyYW1zOiBSZWNvdmVyUGFyYW1zLFxuICB3YWxsZXRLZXlzOiBSb290V2FsbGV0S2V5cyxcbiAgY2hhaW46IENoYWluQ29kZVxuKTogUHJvbWlzZTxXYWxsZXRVbnNwZW50W10+IHtcbiAgY29uc3QgcmVjb3ZlcnlQcm92aWRlciA9IHBhcmFtcy5yZWNvdmVyeVByb3ZpZGVyID8/IGZvckNvaW4oY29pbi5nZXRDaGFpbigpLCBwYXJhbXMuYXBpS2V5KTtcbiAgY29uc3QgTUFYX1NFUVVFTlRJQUxfQUREUkVTU0VTX1dJVEhPVVRfVFhTID0gcGFyYW1zLnNjYW4gfHwgMjA7XG4gIGxldCBudW1TZXF1ZW50aWFsQWRkcmVzc2VzV2l0aG91dFR4cyA9IDA7XG5cbiAgYXN5bmMgZnVuY3Rpb24gZ2F0aGVyVW5zcGVudHMoYWRkckluZGV4OiBudW1iZXIpIHtcbiAgICBjb25zdCB3YWxsZXRLZXlzRm9yVW5zcGVudCA9IHdhbGxldEtleXMuZGVyaXZlRm9yQ2hhaW5BbmRJbmRleChjaGFpbiwgYWRkckluZGV4KTtcbiAgICBjb25zdCBhZGRyZXNzID0gY29pbi5jcmVhdGVNdWx0aVNpZ0FkZHJlc3Moc2NyaXB0VHlwZUZvckNoYWluKGNoYWluKSwgMiwgd2FsbGV0S2V5c0ZvclVuc3BlbnQucHVibGljS2V5cyk7XG5cbiAgICBjb25zdCBhZGRySW5mbyA9IGF3YWl0IHJlY292ZXJ5UHJvdmlkZXIuZ2V0QWRkcmVzc0luZm8oYWRkcmVzcy5hZGRyZXNzKTtcbiAgICAvLyB3ZSB1c2UgdHhDb3VudCBoZXJlIGJlY2F1c2UgaXQgaW1wbGllcyB1c2FnZSAtIGhhdmluZyB0eCdlcyBtZWFucyB0aGUgYWRkciB3YXMgZ2VuZXJhdGVkIGFuZCB1c2VkXG4gICAgaWYgKGFkZHJJbmZvLnR4Q291bnQgPT09IDApIHtcbiAgICAgIG51bVNlcXVlbnRpYWxBZGRyZXNzZXNXaXRob3V0VHhzKys7XG4gICAgfSBlbHNlIHtcbiAgICAgIG51bVNlcXVlbnRpYWxBZGRyZXNzZXNXaXRob3V0VHhzID0gMDtcblxuICAgICAgaWYgKGFkZHJJbmZvLmJhbGFuY2UgPiAwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBGb3VuZCBhbiBhZGRyZXNzIHdpdGggYmFsYW5jZTogJHthZGRyZXNzLmFkZHJlc3N9IHdpdGggYmFsYW5jZSAke2FkZHJJbmZvLmJhbGFuY2V9YCk7XG4gICAgICAgIGNvbnN0IGFkZHJlc3NVbnNwZW50cyA9IGF3YWl0IHJlY292ZXJ5UHJvdmlkZXIuZ2V0VW5zcGVudHNGb3JBZGRyZXNzZXMoW2FkZHJlc3MuYWRkcmVzc10pO1xuXG4gICAgICAgIHdhbGxldFVuc3BlbnRzLnB1c2goXG4gICAgICAgICAgLi4uYWRkcmVzc1Vuc3BlbnRzLm1hcChcbiAgICAgICAgICAgICh1KTogV2FsbGV0VW5zcGVudCA9PiAoe1xuICAgICAgICAgICAgICAuLi51LFxuICAgICAgICAgICAgICBjaGFpbjogY2hhaW4sXG4gICAgICAgICAgICAgIGluZGV4OiBhZGRySW5kZXgsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobnVtU2VxdWVudGlhbEFkZHJlc3Nlc1dpdGhvdXRUeHMgPj0gTUFYX1NFUVVFTlRJQUxfQUREUkVTU0VTX1dJVEhPVVRfVFhTKSB7XG4gICAgICAvLyBzdG9wIHNlYXJjaGluZyBmb3IgYWRkcmVzc2VzIHdpdGggdW5zcGVudHMgaW4gdGhlbSwgd2UndmUgZm91bmQgJHtNQVhfU0VRVUVOVElBTF9BRERSRVNTRVNfV0lUSE9VVF9UWFN9IGluIGEgcm93IHdpdGggbm9uZVxuICAgICAgLy8gd2UgYXJlIGRvbmVcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICByZXR1cm4gZ2F0aGVyVW5zcGVudHMoYWRkckluZGV4ICsgMSk7XG4gIH1cblxuICAvLyBnZXQgdW5zcGVudHMgZm9yIHRoZXNlIGFkZHJlc3Nlc1xuXG4gIGNvbnN0IHdhbGxldFVuc3BlbnRzOiBXYWxsZXRVbnNwZW50W10gPSBbXTtcbiAgLy8gVGhpcyB3aWxsIHBvcHVsYXRlIHdhbGxldEFkZHJlc3Nlc1xuICBhd2FpdCBnYXRoZXJVbnNwZW50cygwKTtcblxuICBpZiAod2FsbGV0VW5zcGVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgLy8gQ291bGRuJ3QgZmluZCBhbnkgYWRkcmVzc2VzIHdpdGggZnVuZHNcbiAgICByZXR1cm4gW107XG4gIH1cblxuICByZXR1cm4gd2FsbGV0VW5zcGVudHM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldFJlY292ZXJ5RmVlUGVyQnl0ZXMoXG4gIGNvaW46IEFic3RyYWN0VXR4b0NvaW4sXG4gIHsgZGVmYXVsdFZhbHVlIH06IHsgZGVmYXVsdFZhbHVlOiBudW1iZXIgfVxuKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgTWVtcG9vbEFwaS5mb3JDb2luKGNvaW4uZ2V0Q2hhaW4oKSkuZ2V0UmVjb3ZlcnlGZWVQZXJCeXRlcygpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgY29uc29sZS5kaXIoZSk7XG4gICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTtcbiAgfVxufVxuXG5leHBvcnQgdHlwZSBCYWNrdXBLZXlSZWNvdmVyeVRyYW5zYW5zYWN0aW9uID0ge1xuICBpbnB1dHM6IFdhbGxldFVuc3BlbnRbXTtcbiAgdHJhbnNhY3Rpb25IZXg6IHN0cmluZztcbiAgY29pbjogc3RyaW5nO1xuICBiYWNrdXBLZXk6IHN0cmluZztcbiAgcmVjb3ZlcnlBbW91bnQ6IG51bWJlcjtcbiAgLy8gc21hcnRiaXQgYXBpIHJlc3BvbnNlXG4gIHR4PzogdW5rbm93bjtcbn07XG5cbi8qKlxuICogQnVpbGRzIGEgZnVuZHMgcmVjb3ZlcnkgdHJhbnNhY3Rpb24gd2l0aG91dCBCaXRHb1xuICogQHBhcmFtIGNvaW5cbiAqIEBwYXJhbSBiaXRnb1xuICogQHBhcmFtIHBhcmFtc1xuICogLSB1c2VyS2V5OiBbZW5jcnlwdGVkXSB4cHJ2LCBvciB4cHViXG4gKiAtIGJhY2t1cEtleTogW2VuY3J5cHRlZF0geHBydiwgb3IgeHB1YiBpZiB0aGUgeHBydiBpcyBoZWxkIGJ5IGEgS1JTIHByb3ZpZGVyXG4gKiAtIHdhbGxldFBhc3NwaHJhc2U6IG5lY2Vzc2FyeSBpZiBvbmUgb2YgdGhlIHhwcnZzIGlzIGVuY3J5cHRlZFxuICogLSBiaXRnb0tleTogeHB1YlxuICogLSBrcnNQcm92aWRlcjogbmVjZXNzYXJ5IGlmIGJhY2t1cCBrZXkgaXMgaGVsZCBieSBLUlNcbiAqIC0gcmVjb3ZlcnlEZXN0aW5hdGlvbjogdGFyZ2V0IGFkZHJlc3MgdG8gc2VuZCByZWNvdmVyZWQgZnVuZHMgdG9cbiAqIC0gc2NhbjogdGhlIGFtb3VudCBvZiBjb25zZWN1dGl2ZSBhZGRyZXNzZXMgd2l0aG91dCB1bnNwZW50cyB0byBzY2FuIHRocm91Z2ggYmVmb3JlIHN0b3BwaW5nXG4gKiAtIGlnbm9yZUFkZHJlc3NUeXBlczogKG9wdGlvbmFsKSBzY3JpcHRzIHRvIGlnbm9yZVxuICogICAgICAgIGZvciBleGFtcGxlOiBbJ3Ayc2hQMndzaCcsICdwMndzaCddIHdpbGwgcHJldmVudCBjb2RlIGZyb20gY2hlY2tpbmcgZm9yIHdyYXBwZWQtc2Vnd2l0IGFuZCBuYXRpdmUtc2Vnd2l0IGNoYWlucyBvbiB0aGUgcHVibGljIGJsb2NrIGV4cGxvcmVyc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYmFja3VwS2V5UmVjb3ZlcnkoXG4gIGNvaW46IEFic3RyYWN0VXR4b0NvaW4sXG4gIGJpdGdvOiBCaXRHb0Jhc2UsXG4gIHBhcmFtczogUmVjb3ZlclBhcmFtc1xuKTogUHJvbWlzZTxCYWNrdXBLZXlSZWNvdmVyeVRyYW5zYW5zYWN0aW9uIHwgRm9ybWF0dGVkT2ZmbGluZVZhdWx0VHhJbmZvPiB7XG4gIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy51c2VyS2V5KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB1c2VyS2V5Jyk7XG4gIH1cblxuICBpZiAoXy5pc1VuZGVmaW5lZChwYXJhbXMuYmFja3VwS2V5KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBiYWNrdXBLZXknKTtcbiAgfVxuXG4gIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKSB8fCAhY29pbi5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgcmVjb3ZlcnlEZXN0aW5hdGlvbicpO1xuICB9XG5cbiAgaWYgKCFfLmlzVW5kZWZpbmVkKHBhcmFtcy5zY2FuKSAmJiAoIV8uaXNJbnRlZ2VyKHBhcmFtcy5zY2FuKSB8fCBwYXJhbXMuc2NhbiA8IDApKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzY2FuIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyJyk7XG4gIH1cblxuICBjb25zdCBpc0tyc1JlY292ZXJ5ID0gZ2V0SXNLcnNSZWNvdmVyeShwYXJhbXMpO1xuICBjb25zdCBpc1Vuc2lnbmVkU3dlZXAgPSBnZXRJc1Vuc2lnbmVkU3dlZXAocGFyYW1zKTtcblxuICBjb25zdCBrcnNQcm92aWRlciA9IGlzS3JzUmVjb3ZlcnkgPyBnZXRLcnNQcm92aWRlcihjb2luLCBwYXJhbXMua3JzUHJvdmlkZXIpIDogdW5kZWZpbmVkO1xuXG4gIC8vIGNoZWNrIHdoZXRoZXIga2V5IG1hdGVyaWFsIGFuZCBwYXNzd29yZCBhdXRoZW50aWNhdGUgdGhlIHVzZXJzIGFuZCByZXR1cm4gcGFyZW50IGtleXMgb2YgYWxsIHRocmVlIGtleXMgb2YgdGhlIHdhbGxldFxuICBjb25zdCBrZXlzID0gZ2V0QmlwMzJLZXlzKGJpdGdvLCBwYXJhbXMsIHsgcmVxdWlyZUJpdEdvWHB1YjogdHJ1ZSB9KTtcbiAgaWYgKCFpc1RyaXBsZShrZXlzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgZXhwZWN0ZWQga2V5IHRyaXBsZWApO1xuICB9XG4gIGNvbnN0IHdhbGxldEtleXMgPSBuZXcgUm9vdFdhbGxldEtleXMoa2V5cywgW1xuICAgIHBhcmFtcy51c2VyS2V5UGF0aCB8fCBSb290V2FsbGV0S2V5cy5kZWZhdWx0UHJlZml4LFxuICAgIFJvb3RXYWxsZXRLZXlzLmRlZmF1bHRQcmVmaXgsXG4gICAgUm9vdFdhbGxldEtleXMuZGVmYXVsdFByZWZpeCxcbiAgXSk7XG5cbiAgY29uc3QgdW5zcGVudHM6IFdhbGxldFVuc3BlbnRbXSA9IChcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG91dHB1dFNjcmlwdHMuc2NyaXB0VHlwZXMyT2YzXG4gICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgKGFkZHJlc3NUeXBlKSA9PiBjb2luLnN1cHBvcnRzQWRkcmVzc1R5cGUoYWRkcmVzc1R5cGUpICYmICFwYXJhbXMuaWdub3JlQWRkcmVzc1R5cGVzPy5pbmNsdWRlcyhhZGRyZXNzVHlwZSlcbiAgICAgICAgKVxuICAgICAgICAucmVkdWNlKFxuICAgICAgICAgIChxdWVyaWVzLCBhZGRyZXNzVHlwZSkgPT4gW1xuICAgICAgICAgICAgLi4ucXVlcmllcyxcbiAgICAgICAgICAgIHF1ZXJ5QmxvY2tjaGFpblVuc3BlbnRzUGF0aChjb2luLCBwYXJhbXMsIHdhbGxldEtleXMsIGdldEV4dGVybmFsQ2hhaW5Db2RlKGFkZHJlc3NUeXBlKSksXG4gICAgICAgICAgICBxdWVyeUJsb2NrY2hhaW5VbnNwZW50c1BhdGgoY29pbiwgcGFyYW1zLCB3YWxsZXRLZXlzLCBnZXRJbnRlcm5hbENoYWluQ29kZShhZGRyZXNzVHlwZSkpLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgW10gYXMgUHJvbWlzZTxXYWxsZXRVbnNwZW50W10+W11cbiAgICAgICAgKVxuICAgIClcbiAgKS5mbGF0KCk7XG5cbiAgLy8gRXhlY3V0ZSB0aGUgcXVlcmllcyBhbmQgZ2F0aGVyIHRoZSB1bnNwZW50c1xuICBjb25zdCB0b3RhbElucHV0QW1vdW50ID0gdW5zcGVudHMucmVkdWNlKChzdW0sIHUpID0+IHN1bSArIHUudmFsdWUsIDApO1xuICBpZiAodG90YWxJbnB1dEFtb3VudCA8PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yTm9JbnB1dFRvUmVjb3ZlcigpO1xuICB9XG5cbiAgLy8gQnVpbGQgdGhlIHRyYW5zYWN0aW9uXG4gIGNvbnN0IHRyYW5zYWN0aW9uQnVpbGRlciA9IHV0eG9saWIuYml0Z28uY3JlYXRlVHJhbnNhY3Rpb25CdWlsZGVyRm9yTmV0d29yayhjb2luLm5ldHdvcmspO1xuICBjb25zdCB0eEluZm8gPSB7fSBhcyBCYWNrdXBLZXlSZWNvdmVyeVRyYW5zYW5zYWN0aW9uO1xuXG4gIGNvbnN0IGZlZVBlckJ5dGU6IG51bWJlciA9IGF3YWl0IGdldFJlY292ZXJ5RmVlUGVyQnl0ZXMoY29pbiwgeyBkZWZhdWx0VmFsdWU6IDEwMCB9KTtcblxuICAvLyBLUlMgcmVjb3ZlcnkgdHJhbnNhY3Rpb25zIGhhdmUgYSAybmQgb3V0cHV0IHRvIHBheSB0aGUgcmVjb3ZlcnkgZmVlLCBsaWtlIHBheWdvIGZlZXMuIFVzZSBwMndzaCBvdXRwdXRzIGJlY2F1c2VcbiAgLy8gdGhleSBhcmUgdGhlIGxhcmdlc3Qgb3V0cHV0cyBhbmQgdGh1cyB0aGUgbW9zdCBjb25zZXJ2YXRpdmUgZXN0aW1hdGUgdG8gdXNlIGluIGNhbGN1bGF0aW5nIGZlZXMuIEFsc28gdXNlXG4gIC8vIHNlZ3dpdCBvdmVyaGVhZCBzaXplIGFuZCBwMnNoIGlucHV0cyBmb3IgdGhlIHNhbWUgcmVhc29uLlxuICBjb25zdCBvdXRwdXRTaXplID0gKGlzS3JzUmVjb3ZlcnkgPyAyIDogMSkgKiBWaXJ0dWFsU2l6ZXMudHhQMndzaE91dHB1dFNpemU7XG4gIGNvbnN0IGFwcHJveGltYXRlU2l6ZSA9IFZpcnR1YWxTaXplcy50eFNlZ092ZXJoZWFkVlNpemUgKyBvdXRwdXRTaXplICsgVmlydHVhbFNpemVzLnR4UDJzaElucHV0U2l6ZSAqIHVuc3BlbnRzLmxlbmd0aDtcbiAgY29uc3QgYXBwcm94aW1hdGVGZWUgPSBhcHByb3hpbWF0ZVNpemUgKiBmZWVQZXJCeXRlO1xuXG4gIC8vIENvbnN0cnVjdCBhIHRyYW5zYWN0aW9uXG4gIHR4SW5mby5pbnB1dHMgPSB1bnNwZW50cztcblxuICB1bnNwZW50cy5mb3JFYWNoKCh1bnNwZW50KSA9PiB7XG4gICAgY29uc3QgeyB0eGlkLCB2b3V0IH0gPSBwYXJzZU91dHB1dElkKHVuc3BlbnQuaWQpO1xuICAgIHRyYW5zYWN0aW9uQnVpbGRlci5hZGRJbnB1dChcbiAgICAgIHR4aWQsXG4gICAgICB2b3V0LFxuICAgICAgMHhmZmZmZmZmZixcbiAgICAgIHV0eG9saWIuYWRkcmVzcy50b091dHB1dFNjcmlwdCh1bnNwZW50LmFkZHJlc3MsIGNvaW4ubmV0d29yayksXG4gICAgICB1bnNwZW50LnZhbHVlXG4gICAgKTtcbiAgfSk7XG5cbiAgbGV0IHJlY292ZXJ5QW1vdW50ID0gdG90YWxJbnB1dEFtb3VudCAtIGFwcHJveGltYXRlRmVlO1xuICBsZXQga3JzRmVlO1xuICBpZiAoaXNLcnNSZWNvdmVyeSAmJiBwYXJhbXMua3JzUHJvdmlkZXIpIHtcbiAgICB0cnkge1xuICAgICAga3JzRmVlID0gYXdhaXQgY2FsY3VsYXRlRmVlQW1vdW50KGNvaW4sIHtcbiAgICAgICAgcHJvdmlkZXI6IHBhcmFtcy5rcnNQcm92aWRlcixcbiAgICAgICAgYW1vdW50OiByZWNvdmVyeUFtb3VudCxcbiAgICAgIH0pO1xuICAgICAgcmVjb3ZlcnlBbW91bnQgLT0ga3JzRmVlO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgLy8gRG9uJ3QgbGV0IHRoaXMgZXJyb3IgYmxvY2sgdGhlIHJlY292ZXJ5IC1cbiAgICAgIGNvbnNvbGUuZGlyKGVycik7XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlY292ZXJ5QW1vdW50IDwgMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgdGhpcyB3YWxsZXRcXCdzIGJhbGFuY2UgaXMgdG9vIGxvdyB0byBwYXkgdGhlIGZlZXMgc3BlY2lmaWVkIGJ5IHRoZSBLUlMgcHJvdmlkZXIuIFxuICAgICAgICAgIEV4aXN0aW5nIGJhbGFuY2Ugb24gd2FsbGV0OiAke3RvdGFsSW5wdXRBbW91bnR9LiBFc3RpbWF0ZWQgbmV0d29yayBmZWUgZm9yIHRoZSByZWNvdmVyeSB0cmFuc2FjdGlvblxuICAgICAgICAgIDogJHthcHByb3hpbWF0ZUZlZX0sIEtSUyBmZWUgdG8gcGF5OiAke2tyc0ZlZX0uIEFmdGVyIGRlZHVjdGluZyBmZWVzLCB5b3VyIHRvdGFsIHJlY292ZXJhYmxlIGJhbGFuY2VcbiAgICAgICAgICBpcyAke3JlY292ZXJ5QW1vdW50fWApO1xuICB9XG5cbiAgdHJhbnNhY3Rpb25CdWlsZGVyLmFkZE91dHB1dChwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiwgcmVjb3ZlcnlBbW91bnQpO1xuXG4gIGlmIChrcnNQcm92aWRlciAmJiBrcnNGZWUgPiAwKSB7XG4gICAgaWYgKCFrcnNQcm92aWRlci5mZWVBZGRyZXNzZXMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihga2V5UHJvdmlkZXIgbXVzdCBkZWZpbmUgZmVlQWRkcmVzc2VzYCk7XG4gICAgfVxuXG4gICAgY29uc3Qga3JzRmVlQWRkcmVzcyA9IGtyc1Byb3ZpZGVyLmZlZUFkZHJlc3Nlc1tjb2luLmdldENoYWluKCldO1xuXG4gICAgaWYgKCFrcnNGZWVBZGRyZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RoaXMgS1JTIHByb3ZpZGVyIGhhcyBub3QgY29uZmlndXJlZCB0aGVpciBmZWUgc3RydWN0dXJlIHlldCAtIHJlY292ZXJ5IGNhbm5vdCBiZSBjb21wbGV0ZWQnKTtcbiAgICB9XG5cbiAgICB0cmFuc2FjdGlvbkJ1aWxkZXIuYWRkT3V0cHV0KGtyc0ZlZUFkZHJlc3MsIGtyc0ZlZSk7XG4gIH1cblxuICBpZiAoaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgY29uc3QgdHhIZXggPSB0cmFuc2FjdGlvbkJ1aWxkZXIuYnVpbGRJbmNvbXBsZXRlKCkudG9CdWZmZXIoKS50b1N0cmluZygnaGV4Jyk7XG4gICAgcmV0dXJuIGZvcm1hdEZvck9mZmxpbmVWYXVsdChjb2luLmdldENoYWluKCksIHR4SW5mbyBhcyBPZmZsaW5lVmF1bHRUeEluZm8sIHR4SGV4KTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgdHJhbnNhY3Rpb24gPSBzaWduQW5kVmVyaWZ5V2FsbGV0VHJhbnNhY3Rpb24oXG4gICAgICB0cmFuc2FjdGlvbkJ1aWxkZXIsXG4gICAgICB1bnNwZW50cyxcbiAgICAgIG5ldyBXYWxsZXRVbnNwZW50U2lnbmVyPFJvb3RXYWxsZXRLZXlzPih3YWxsZXRLZXlzLCB3YWxsZXRLZXlzLnVzZXIsIHdhbGxldEtleXMuYmFja3VwKSxcbiAgICAgIHsgaXNMYXN0U2lnbmF0dXJlOiBmYWxzZSB9XG4gICAgKTtcbiAgICBpZiAoIWlzS3JzUmVjb3ZlcnkpIHtcbiAgICAgIHRyYW5zYWN0aW9uID0gc2lnbkFuZFZlcmlmeVdhbGxldFRyYW5zYWN0aW9uKFxuICAgICAgICB0cmFuc2FjdGlvbixcbiAgICAgICAgdW5zcGVudHMsXG4gICAgICAgIG5ldyBXYWxsZXRVbnNwZW50U2lnbmVyPFJvb3RXYWxsZXRLZXlzPih3YWxsZXRLZXlzLCB3YWxsZXRLZXlzLmJhY2t1cCwgd2FsbGV0S2V5cy51c2VyKSxcbiAgICAgICAgeyBpc0xhc3RTaWduYXR1cmU6IHRydWUgfVxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0eEluZm8udHJhbnNhY3Rpb25IZXggPSB0cmFuc2FjdGlvbi50b0J1ZmZlcigpLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgIGxldCB0cmFuc2FjdGlvbkRldGFpbHM7XG4gICAgdHJ5IHtcbiAgICAgIHRyYW5zYWN0aW9uRGV0YWlscyA9IGF3YWl0IFNtYXJ0Yml0QXBpLmZvckNvaW4oY29pbi5nZXRDaGFpbigpKS5nZXRUcmFuc2FjdGlvbkRldGFpbHModHJhbnNhY3Rpb24pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIHNvbWUgY29pbnMgZG9uJ3QgaGF2ZSBhIHJlbGlhYmxlIHRoaXJkIHBhcnR5IHZlcmlmaWNhdGlvbiBlbmRwb2ludCwgb3Igc29tZXRpbWVzIHRoZSB0aGlyZCBwYXJ0eSBlbmRwb2ludFxuICAgICAgLy8gY291bGQgYmUgdW5hdmFpbGFibGUgZHVlIHRvIHNlcnZpY2Ugb3V0YWdlLCBzbyB3ZSBjb250aW51ZSB3aXRob3V0IHZlcmlmaWNhdGlvbiBmb3IgdGhvc2UgY29pbnMsIGJ1dCB3ZSB3aWxsXG4gICAgICAvLyBsZXQgdXNlcnMga25vdyB0aGF0IHRoZXkgc2hvdWxkIHZlcmlmeSB0aGVpciBvd25cbiAgICAgIC8vIHRoaXMgbWVzc2FnZSBzaG91bGQgYmUgcGlwZWQgdG8gV1JXIGFuZCBkaXNwbGF5ZWQgb24gdGhlIFVJXG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIEFwaU5vdEltcGxlbWVudGVkRXJyb3IgfHwgZSBpbnN0YW5jZW9mIEFwaVJlcXVlc3RFcnJvcikge1xuICAgICAgICBjb25zb2xlLmxvZygnUGxlYXNlIHZlcmlmeSB5b3VyIHRyYW5zYWN0aW9uIGJ5IGRlY29kaW5nIHRoZSB0eCBoZXggdXNpbmcgYSB0aGlyZC1wYXJ0eSBhcGkgb2YgeW91ciBjaG9pY2UnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRyYW5zYWN0aW9uRGV0YWlscykge1xuICAgICAgLyoqXG4gICAgICAgKiBWZXJpZnkgdGhhdCB0aGUgdHhoZXggdXNlciBzaWducyBjb3JyZXNwb25kIHRvIHRoZSBjb3JyZWN0IHR4IHRoZXkgaW50ZW5kZWRcbiAgICAgICAqIGJ5IDEpIGdldHRpbmcgYmFjayB0aGUgZGVjb2RlZCB0cmFuc2FjdGlvbiBiYXNlZCBvbiB0aGUgdHhoZXhcbiAgICAgICAqIGFuZCB0aGVuIDIpIGNvbXB1dGUgdGhlIHR4aWQgKGhhc2gpLCBoMSBvZiB0aGUgZGVjb2RlZCB0cmFuc2FjdGlvbiAzKSBjb21wYXJlIGgxXG4gICAgICAgKiB0byB0aGUgdHhpZCAoaGFzaCkgb2YgdGhlIHRyYW5zYWN0aW9uIChpbmNsdWRpbmcgdW5zcGVudCBpbmZvKSB3ZSBjb25zdHJ1Y3RlZFxuICAgICAgICovXG4gICAgICBpZiAodHJhbnNhY3Rpb25EZXRhaWxzLlR4SWQgIT09IHRyYW5zYWN0aW9uLmdldElkKCkpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ3R4aGFzaC90eGlkIHJldHVybmVkIGJ5IGJsb2NrZXhwbG9yZXI6ICcsIHRyYW5zYWN0aW9uRGV0YWlscy5UeElkKTtcbiAgICAgICAgY29uc29sZS5sb2coJ3R4aGFzaC90eGlkIG9mIHRoZSB0cmFuc2FjdGlvbiBiaXRnbyBjb25zdHJ1Y3RlZCcsIHRyYW5zYWN0aW9uLmdldElkKCkpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2luY29uc2lzdGVudCByZWNvdmVyeSB0cmFuc2FjdGlvbiBpZCcpO1xuICAgICAgfVxuICAgICAgdHhJbmZvLnR4ID0gdHJhbnNhY3Rpb25EZXRhaWxzO1xuICAgIH1cbiAgfVxuXG4gIGlmIChpc0tyc1JlY292ZXJ5KSB7XG4gICAgdHhJbmZvLmNvaW4gPSBjb2luLmdldENoYWluKCk7XG4gICAgdHhJbmZvLmJhY2t1cEtleSA9IHBhcmFtcy5iYWNrdXBLZXk7XG4gICAgdHhJbmZvLnJlY292ZXJ5QW1vdW50ID0gcmVjb3ZlcnlBbW91bnQ7XG4gIH1cblxuICByZXR1cm4gdHhJbmZvO1xufVxuIl19
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @prettier
|
|
3
|
+
*/
|
|
4
|
+
import * as superagent from 'superagent';
|
|
5
|
+
import { BitGoJsError } from '@bitgo/sdk-core';
|
|
6
|
+
export declare class ApiNotImplementedError extends BitGoJsError {
|
|
7
|
+
constructor(coinName: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class ApiRequestError extends BitGoJsError {
|
|
10
|
+
constructor(url: string, reason: Error | string);
|
|
11
|
+
static forRequest(req: superagent.Request, reason: Error | string): ApiRequestError;
|
|
12
|
+
static forResponse(res: superagent.Response, reason: Error | string): ApiRequestError;
|
|
13
|
+
}
|
|
14
|
+
export declare type RequestOptions = {
|
|
15
|
+
retry?: number;
|
|
16
|
+
};
|
|
17
|
+
export declare type Response<T> = {
|
|
18
|
+
map<V>(f: (body: T) => V): V;
|
|
19
|
+
};
|
|
20
|
+
export declare class BaseApi {
|
|
21
|
+
baseUrl: string;
|
|
22
|
+
constructor(baseUrl: string);
|
|
23
|
+
request<T>(method: string, path: string, requestBody: unknown | undefined, params?: RequestOptions): Promise<Response<T>>;
|
|
24
|
+
get<T>(path: string, params?: RequestOptions): Promise<Response<T>>;
|
|
25
|
+
post<T>(path: string, body: unknown, params?: RequestOptions): Promise<Response<T>>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=baseApi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseApi.d.ts","sourceRoot":"","sources":["../../../src/recovery/baseApi.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,qBAAa,sBAAuB,SAAQ,YAAY;gBAC1C,QAAQ,EAAE,MAAM;CAG7B;AAED,qBAAa,eAAgB,SAAQ,YAAY;gBACnC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAG,MAAM;IAI/C,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,eAAe;IAInF,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,eAAe;CAGtF;AAED,oBAAY,cAAc,GAAG;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,oBAAY,QAAQ,CAAC,CAAC,IAAI;IACxB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;CAC9B,CAAC;AAEF,qBAAa,OAAO;IACC,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM;IAS5B,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,OAAO,GAAG,SAAS,EAChC,MAAM,GAAE,cAAmB,GAC1B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IA4BvB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAInE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;CAGpF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseApi = exports.ApiRequestError = exports.ApiNotImplementedError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @prettier
|
|
6
|
+
*/
|
|
7
|
+
const superagent = require("superagent");
|
|
8
|
+
const sdk_core_1 = require("@bitgo/sdk-core");
|
|
9
|
+
class ApiNotImplementedError extends sdk_core_1.BitGoJsError {
|
|
10
|
+
constructor(coinName) {
|
|
11
|
+
super(`api not implemented for coin ${coinName}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.ApiNotImplementedError = ApiNotImplementedError;
|
|
15
|
+
class ApiRequestError extends sdk_core_1.BitGoJsError {
|
|
16
|
+
constructor(url, reason) {
|
|
17
|
+
super(`error in API request: ${url}: ${reason}`);
|
|
18
|
+
}
|
|
19
|
+
static forRequest(req, reason) {
|
|
20
|
+
return new ApiRequestError(req.toString(), reason);
|
|
21
|
+
}
|
|
22
|
+
static forResponse(res, reason) {
|
|
23
|
+
return new ApiRequestError(res.header, reason);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.ApiRequestError = ApiRequestError;
|
|
27
|
+
class BaseApi {
|
|
28
|
+
constructor(baseUrl) {
|
|
29
|
+
this.baseUrl = baseUrl;
|
|
30
|
+
if (!baseUrl.startsWith('https://')) {
|
|
31
|
+
throw new Error(`baseUrl must start with https://`);
|
|
32
|
+
}
|
|
33
|
+
if (baseUrl.endsWith(`/`)) {
|
|
34
|
+
throw new Error(`baseUrl must not end with slash (/)`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async request(method, path, requestBody, params = {}) {
|
|
38
|
+
if (!path.startsWith(path)) {
|
|
39
|
+
throw new Error(`path must start with '/' character`);
|
|
40
|
+
}
|
|
41
|
+
const url = this.baseUrl + path;
|
|
42
|
+
let response;
|
|
43
|
+
try {
|
|
44
|
+
response = await superagent(method, url)
|
|
45
|
+
.retry(params.retry)
|
|
46
|
+
.send(requestBody);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
throw new ApiRequestError(url, e);
|
|
50
|
+
}
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
throw new ApiRequestError(url, `status code ${response.statusCode}`);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
map(f) {
|
|
56
|
+
try {
|
|
57
|
+
return f(response.body);
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
throw new ApiRequestError(url, e);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
get(path, params) {
|
|
66
|
+
return this.request('get', path, undefined, params);
|
|
67
|
+
}
|
|
68
|
+
post(path, body, params) {
|
|
69
|
+
return this.request('post', path, body, params);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.BaseApi = BaseApi;
|
|
73
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZUFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9yZWNvdmVyeS9iYXNlQXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOztHQUVHO0FBQ0gseUNBQXlDO0FBQ3pDLDhDQUErQztBQUUvQyxNQUFhLHNCQUF1QixTQUFRLHVCQUFZO0lBQ3RELFlBQVksUUFBZ0I7UUFDMUIsS0FBSyxDQUFDLGdDQUFnQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ3BELENBQUM7Q0FDRjtBQUpELHdEQUlDO0FBRUQsTUFBYSxlQUFnQixTQUFRLHVCQUFZO0lBQy9DLFlBQVksR0FBVyxFQUFFLE1BQXNCO1FBQzdDLEtBQUssQ0FBQyx5QkFBeUIsR0FBRyxLQUFLLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVELE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBdUIsRUFBRSxNQUFzQjtRQUMvRCxPQUFPLElBQUksZUFBZSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRUQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxHQUF3QixFQUFFLE1BQXNCO1FBQ2pFLE9BQU8sSUFBSSxlQUFlLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNqRCxDQUFDO0NBQ0Y7QUFaRCwwQ0FZQztBQVVELE1BQWEsT0FBTztJQUNsQixZQUFtQixPQUFlO1FBQWYsWUFBTyxHQUFQLE9BQU8sQ0FBUTtRQUNoQyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtZQUNuQyxNQUFNLElBQUksS0FBSyxDQUFDLGtDQUFrQyxDQUFDLENBQUM7U0FDckQ7UUFDRCxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDekIsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQ0FBcUMsQ0FBQyxDQUFDO1NBQ3hEO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxPQUFPLENBQ1gsTUFBYyxFQUNkLElBQVksRUFDWixXQUFnQyxFQUNoQyxTQUF5QixFQUFFO1FBRTNCLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsb0NBQW9DLENBQUMsQ0FBQztTQUN2RDtRQUNELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQ2hDLElBQUksUUFBUSxDQUFDO1FBQ2IsSUFBSTtZQUNGLFFBQVEsR0FBRyxNQUFNLFVBQVUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDO2lCQUNyQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQztpQkFDbkIsSUFBSSxDQUFDLFdBQXNDLENBQUMsQ0FBQztTQUNqRDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsTUFBTSxJQUFJLGVBQWUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDbkM7UUFDRCxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsRUFBRTtZQUNoQixNQUFNLElBQUksZUFBZSxDQUFDLEdBQUcsRUFBRSxlQUFlLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1NBQ3RFO1FBRUQsT0FBTztZQUNMLEdBQUcsQ0FBSSxDQUFpQjtnQkFDdEIsSUFBSTtvQkFDRixPQUFPLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7aUJBQ3pCO2dCQUFDLE9BQU8sQ0FBQyxFQUFFO29CQUNWLE1BQU0sSUFBSSxlQUFlLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO2lCQUNuQztZQUNILENBQUM7U0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELEdBQUcsQ0FBSSxJQUFZLEVBQUUsTUFBdUI7UUFDMUMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFFRCxJQUFJLENBQUksSUFBWSxFQUFFLElBQWEsRUFBRSxNQUF1QjtRQUMxRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDbEQsQ0FBQztDQUNGO0FBbERELDBCQWtEQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHByZXR0aWVyXG4gKi9cbmltcG9ydCAqIGFzIHN1cGVyYWdlbnQgZnJvbSAnc3VwZXJhZ2VudCc7XG5pbXBvcnQgeyBCaXRHb0pzRXJyb3IgfSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuXG5leHBvcnQgY2xhc3MgQXBpTm90SW1wbGVtZW50ZWRFcnJvciBleHRlbmRzIEJpdEdvSnNFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGNvaW5OYW1lOiBzdHJpbmcpIHtcbiAgICBzdXBlcihgYXBpIG5vdCBpbXBsZW1lbnRlZCBmb3IgY29pbiAke2NvaW5OYW1lfWApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBBcGlSZXF1ZXN0RXJyb3IgZXh0ZW5kcyBCaXRHb0pzRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcih1cmw6IHN0cmluZywgcmVhc29uOiBFcnJvciB8IHN0cmluZykge1xuICAgIHN1cGVyKGBlcnJvciBpbiBBUEkgcmVxdWVzdDogJHt1cmx9OiAke3JlYXNvbn1gKTtcbiAgfVxuXG4gIHN0YXRpYyBmb3JSZXF1ZXN0KHJlcTogc3VwZXJhZ2VudC5SZXF1ZXN0LCByZWFzb246IEVycm9yIHwgc3RyaW5nKTogQXBpUmVxdWVzdEVycm9yIHtcbiAgICByZXR1cm4gbmV3IEFwaVJlcXVlc3RFcnJvcihyZXEudG9TdHJpbmcoKSwgcmVhc29uKTtcbiAgfVxuXG4gIHN0YXRpYyBmb3JSZXNwb25zZShyZXM6IHN1cGVyYWdlbnQuUmVzcG9uc2UsIHJlYXNvbjogRXJyb3IgfCBzdHJpbmcpOiBBcGlSZXF1ZXN0RXJyb3Ige1xuICAgIHJldHVybiBuZXcgQXBpUmVxdWVzdEVycm9yKHJlcy5oZWFkZXIsIHJlYXNvbik7XG4gIH1cbn1cblxuZXhwb3J0IHR5cGUgUmVxdWVzdE9wdGlvbnMgPSB7XG4gIHJldHJ5PzogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2U8VD4gPSB7XG4gIG1hcDxWPihmOiAoYm9keTogVCkgPT4gVik6IFY7XG59O1xuXG5leHBvcnQgY2xhc3MgQmFzZUFwaSB7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBiYXNlVXJsOiBzdHJpbmcpIHtcbiAgICBpZiAoIWJhc2VVcmwuc3RhcnRzV2l0aCgnaHR0cHM6Ly8nKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBiYXNlVXJsIG11c3Qgc3RhcnQgd2l0aCBodHRwczovL2ApO1xuICAgIH1cbiAgICBpZiAoYmFzZVVybC5lbmRzV2l0aChgL2ApKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGJhc2VVcmwgbXVzdCBub3QgZW5kIHdpdGggc2xhc2ggKC8pYCk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgcmVxdWVzdDxUPihcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICBwYXRoOiBzdHJpbmcsXG4gICAgcmVxdWVzdEJvZHk6IHVua25vd24gfCB1bmRlZmluZWQsXG4gICAgcGFyYW1zOiBSZXF1ZXN0T3B0aW9ucyA9IHt9XG4gICk6IFByb21pc2U8UmVzcG9uc2U8VD4+IHtcbiAgICBpZiAoIXBhdGguc3RhcnRzV2l0aChwYXRoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBwYXRoIG11c3Qgc3RhcnQgd2l0aCAnLycgY2hhcmFjdGVyYCk7XG4gICAgfVxuICAgIGNvbnN0IHVybCA9IHRoaXMuYmFzZVVybCArIHBhdGg7XG4gICAgbGV0IHJlc3BvbnNlO1xuICAgIHRyeSB7XG4gICAgICByZXNwb25zZSA9IGF3YWl0IHN1cGVyYWdlbnQobWV0aG9kLCB1cmwpXG4gICAgICAgIC5yZXRyeShwYXJhbXMucmV0cnkpXG4gICAgICAgIC5zZW5kKHJlcXVlc3RCb2R5IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgQXBpUmVxdWVzdEVycm9yKHVybCwgZSk7XG4gICAgfVxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIHRocm93IG5ldyBBcGlSZXF1ZXN0RXJyb3IodXJsLCBgc3RhdHVzIGNvZGUgJHtyZXNwb25zZS5zdGF0dXNDb2RlfWApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBtYXA8Vj4oZjogKGJvZHk6IFQpID0+IFYpOiBWIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gZihyZXNwb25zZS5ib2R5KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHRocm93IG5ldyBBcGlSZXF1ZXN0RXJyb3IodXJsLCBlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgZ2V0PFQ+KHBhdGg6IHN0cmluZywgcGFyYW1zPzogUmVxdWVzdE9wdGlvbnMpOiBQcm9taXNlPFJlc3BvbnNlPFQ+PiB7XG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdCgnZ2V0JywgcGF0aCwgdW5kZWZpbmVkLCBwYXJhbXMpO1xuICB9XG5cbiAgcG9zdDxUPihwYXRoOiBzdHJpbmcsIGJvZHk6IHVua25vd24sIHBhcmFtcz86IFJlcXVlc3RPcHRpb25zKTogUHJvbWlzZTxSZXNwb25zZTxUPj4ge1xuICAgIHJldHVybiB0aGlzLnJlcXVlc3QoJ3Bvc3QnLCBwYXRoLCBib2R5LCBwYXJhbXMpO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coingeckoApi.d.ts","sourceRoot":"","sources":["../../../src/recovery/coingeckoApi.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,qBAAa,YAAa,SAAQ,OAAO;;IAKjC,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAwBvD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CoingeckoApi = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @prettier
|
|
6
|
+
*/
|
|
7
|
+
const baseApi_1 = require("./baseApi");
|
|
8
|
+
const familyNamesToCoinGeckoIds = new Map()
|
|
9
|
+
.set('BTC', 'bitcoin')
|
|
10
|
+
.set('LTC', 'litecoin')
|
|
11
|
+
.set('BCH', 'bitcoin-cash')
|
|
12
|
+
.set('ZEC', 'zcash')
|
|
13
|
+
.set('DASH', 'dash')
|
|
14
|
+
// note: we don't have a source for price data of BCHA and BSV, but we will use BCH as a proxy. We will substitute
|
|
15
|
+
// it out for a better source when it becomes available. TODO BG-26359.
|
|
16
|
+
.set('BCHA', 'bitcoin-cash')
|
|
17
|
+
.set('BSV', 'bitcoin-cash');
|
|
18
|
+
class CoingeckoApi extends baseApi_1.BaseApi {
|
|
19
|
+
constructor() {
|
|
20
|
+
super('https://api.coingecko.com/api/v3');
|
|
21
|
+
}
|
|
22
|
+
async getUSDPrice(coinFamily) {
|
|
23
|
+
const coinGeckoId = familyNamesToCoinGeckoIds.get(coinFamily.toUpperCase());
|
|
24
|
+
if (!coinGeckoId) {
|
|
25
|
+
throw new Error(`There is no CoinGecko id for family name ${coinFamily.toUpperCase()}.`);
|
|
26
|
+
}
|
|
27
|
+
const coinGeckoUrl = `/simple/price?ids=${coinGeckoId}&vs_currencies=USD`;
|
|
28
|
+
const res = await this.get(coinGeckoUrl, { retry: 2 });
|
|
29
|
+
return res.map((body) => {
|
|
30
|
+
// An example of response
|
|
31
|
+
// {
|
|
32
|
+
// "ethereum": {
|
|
33
|
+
// "usd": 220.64
|
|
34
|
+
// }
|
|
35
|
+
// }
|
|
36
|
+
if (!body) {
|
|
37
|
+
throw new Error('Unable to reach Coin Gecko API for price data');
|
|
38
|
+
}
|
|
39
|
+
if (!body[coinGeckoId]['usd'] || typeof body[coinGeckoId]['usd'] !== 'number') {
|
|
40
|
+
throw new Error('Unexpected response from Coin Gecko API for price data');
|
|
41
|
+
}
|
|
42
|
+
return body[coinGeckoId]['usd'];
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.CoingeckoApi = CoingeckoApi;
|
|
47
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29pbmdlY2tvQXBpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3JlY292ZXJ5L2NvaW5nZWNrb0FwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7R0FFRztBQUNILHVDQUFvQztBQUVwQyxNQUFNLHlCQUF5QixHQUFHLElBQUksR0FBRyxFQUFFO0tBQ3hDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDO0tBQ3JCLEdBQUcsQ0FBQyxLQUFLLEVBQUUsVUFBVSxDQUFDO0tBQ3RCLEdBQUcsQ0FBQyxLQUFLLEVBQUUsY0FBYyxDQUFDO0tBQzFCLEdBQUcsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDO0tBQ25CLEdBQUcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDO0lBQ3BCLGtIQUFrSDtJQUNsSCx3RUFBd0U7S0FDdkUsR0FBRyxDQUFDLE1BQU0sRUFBRSxjQUFjLENBQUM7S0FDM0IsR0FBRyxDQUFDLEtBQUssRUFBRSxjQUFjLENBQUMsQ0FBQztBQUU5QixNQUFhLFlBQWEsU0FBUSxpQkFBTztJQUN2QztRQUNFLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVyxDQUFDLFVBQWtCO1FBQ2xDLE1BQU0sV0FBVyxHQUFHLHlCQUF5QixDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUM1RSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsNENBQTRDLFVBQVUsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDMUY7UUFDRCxNQUFNLFlBQVksR0FBRyxxQkFBcUIsV0FBVyxvQkFBb0IsQ0FBQztRQUMxRSxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQU0sWUFBWSxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUQsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDdEIseUJBQXlCO1lBQ3pCLElBQUk7WUFDSixrQkFBa0I7WUFDbEIsb0JBQW9CO1lBQ3BCLE1BQU07WUFDTixJQUFJO1lBQ0osSUFBSSxDQUFDLElBQUksRUFBRTtnQkFDVCxNQUFNLElBQUksS0FBSyxDQUFDLCtDQUErQyxDQUFDLENBQUM7YUFDbEU7WUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLFFBQVEsRUFBRTtnQkFDN0UsTUFBTSxJQUFJLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO2FBQzNFO1lBRUQsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbEMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUE3QkQsb0NBNkJDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuaW1wb3J0IHsgQmFzZUFwaSB9IGZyb20gJy4vYmFzZUFwaSc7XG5cbmNvbnN0IGZhbWlseU5hbWVzVG9Db2luR2Vja29JZHMgPSBuZXcgTWFwKClcbiAgLnNldCgnQlRDJywgJ2JpdGNvaW4nKVxuICAuc2V0KCdMVEMnLCAnbGl0ZWNvaW4nKVxuICAuc2V0KCdCQ0gnLCAnYml0Y29pbi1jYXNoJylcbiAgLnNldCgnWkVDJywgJ3pjYXNoJylcbiAgLnNldCgnREFTSCcsICdkYXNoJylcbiAgLy8gbm90ZTogd2UgZG9uJ3QgaGF2ZSBhIHNvdXJjZSBmb3IgcHJpY2UgZGF0YSBvZiBCQ0hBIGFuZCBCU1YsIGJ1dCB3ZSB3aWxsIHVzZSBCQ0ggYXMgYSBwcm94eS4gV2Ugd2lsbCBzdWJzdGl0dXRlXG4gIC8vIGl0IG91dCBmb3IgYSBiZXR0ZXIgc291cmNlIHdoZW4gaXQgYmVjb21lcyBhdmFpbGFibGUuICBUT0RPIEJHLTI2MzU5LlxuICAuc2V0KCdCQ0hBJywgJ2JpdGNvaW4tY2FzaCcpXG4gIC5zZXQoJ0JTVicsICdiaXRjb2luLWNhc2gnKTtcblxuZXhwb3J0IGNsYXNzIENvaW5nZWNrb0FwaSBleHRlbmRzIEJhc2VBcGkge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcignaHR0cHM6Ly9hcGkuY29pbmdlY2tvLmNvbS9hcGkvdjMnKTtcbiAgfVxuXG4gIGFzeW5jIGdldFVTRFByaWNlKGNvaW5GYW1pbHk6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgY29pbkdlY2tvSWQgPSBmYW1pbHlOYW1lc1RvQ29pbkdlY2tvSWRzLmdldChjb2luRmFtaWx5LnRvVXBwZXJDYXNlKCkpO1xuICAgIGlmICghY29pbkdlY2tvSWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlcmUgaXMgbm8gQ29pbkdlY2tvIGlkIGZvciBmYW1pbHkgbmFtZSAke2NvaW5GYW1pbHkudG9VcHBlckNhc2UoKX0uYCk7XG4gICAgfVxuICAgIGNvbnN0IGNvaW5HZWNrb1VybCA9IGAvc2ltcGxlL3ByaWNlP2lkcz0ke2NvaW5HZWNrb0lkfSZ2c19jdXJyZW5jaWVzPVVTRGA7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5nZXQ8YW55Pihjb2luR2Vja29VcmwsIHsgcmV0cnk6IDIgfSk7XG4gICAgcmV0dXJuIHJlcy5tYXAoKGJvZHkpID0+IHtcbiAgICAgIC8vIEFuIGV4YW1wbGUgb2YgcmVzcG9uc2VcbiAgICAgIC8vIHtcbiAgICAgIC8vICAgXCJldGhlcmV1bVwiOiB7XG4gICAgICAvLyAgICAgXCJ1c2RcIjogMjIwLjY0XG4gICAgICAvLyAgIH1cbiAgICAgIC8vIH1cbiAgICAgIGlmICghYm9keSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byByZWFjaCBDb2luIEdlY2tvIEFQSSBmb3IgcHJpY2UgZGF0YScpO1xuICAgICAgfVxuICAgICAgaWYgKCFib2R5W2NvaW5HZWNrb0lkXVsndXNkJ10gfHwgdHlwZW9mIGJvZHlbY29pbkdlY2tvSWRdWyd1c2QnXSAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmV4cGVjdGVkIHJlc3BvbnNlIGZyb20gQ29pbiBHZWNrbyBBUEkgZm9yIHByaWNlIGRhdGEnKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGJvZHlbY29pbkdlY2tvSWRdWyd1c2QnXTtcbiAgICB9KTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Unspent } from '@bitgo/utxo-lib/dist/src/bitgo';
|
|
2
|
+
import { BitGoBase, IWallet } from '@bitgo/sdk-core';
|
|
3
|
+
import { AbstractUtxoCoin, TransactionInfo } from '../abstractUtxoCoin';
|
|
4
|
+
export interface ExplorerTxInfo {
|
|
5
|
+
input: {
|
|
6
|
+
address: string;
|
|
7
|
+
}[];
|
|
8
|
+
outputs: {
|
|
9
|
+
address: string;
|
|
10
|
+
}[];
|
|
11
|
+
}
|
|
12
|
+
export declare class BitgoPublicApi {
|
|
13
|
+
coin: AbstractUtxoCoin;
|
|
14
|
+
constructor(coin: AbstractUtxoCoin);
|
|
15
|
+
getTransactionInfo(txid: string): Promise<ExplorerTxInfo>;
|
|
16
|
+
/**
|
|
17
|
+
* Fetch unspent transaction outputs using IMS unspents API
|
|
18
|
+
* @param addresses
|
|
19
|
+
* @returns {*}
|
|
20
|
+
*/
|
|
21
|
+
getUnspentInfo(addresses: string[]): Promise<Unspent[]>;
|
|
22
|
+
}
|
|
23
|
+
export interface BuildRecoveryTransactionOptions {
|
|
24
|
+
wallet: string;
|
|
25
|
+
faultyTxId: string;
|
|
26
|
+
recoveryAddress: string;
|
|
27
|
+
}
|
|
28
|
+
declare type FeeInfo = {
|
|
29
|
+
size: number;
|
|
30
|
+
feeRate: number;
|
|
31
|
+
fee: number;
|
|
32
|
+
payGoFee: number;
|
|
33
|
+
};
|
|
34
|
+
export interface CrossChainRecoveryUnsigned {
|
|
35
|
+
txHex: string;
|
|
36
|
+
txInfo: TransactionInfo;
|
|
37
|
+
walletId: string;
|
|
38
|
+
feeInfo: FeeInfo;
|
|
39
|
+
address: string;
|
|
40
|
+
coin: string;
|
|
41
|
+
}
|
|
42
|
+
export interface CrossChainRecoverySigned {
|
|
43
|
+
version: 1 | 2;
|
|
44
|
+
txHex: string;
|
|
45
|
+
txInfo: TransactionInfo;
|
|
46
|
+
walletId: string;
|
|
47
|
+
sourceCoin: string;
|
|
48
|
+
recoveryCoin: string;
|
|
49
|
+
recoveryAddress?: string;
|
|
50
|
+
recoveryAmount?: number;
|
|
51
|
+
}
|
|
52
|
+
declare type WalletV1 = {
|
|
53
|
+
keychains: {
|
|
54
|
+
xpub: string;
|
|
55
|
+
}[];
|
|
56
|
+
address({ address: string }: {
|
|
57
|
+
address: any;
|
|
58
|
+
}): Promise<{
|
|
59
|
+
chain: number;
|
|
60
|
+
index: number;
|
|
61
|
+
}>;
|
|
62
|
+
getEncryptedUserKeychain(): Promise<{
|
|
63
|
+
encryptedXprv: string;
|
|
64
|
+
}>;
|
|
65
|
+
};
|
|
66
|
+
export declare function getWallet(bitgo: BitGoBase, coin: AbstractUtxoCoin, walletId: string): Promise<IWallet | WalletV1>;
|
|
67
|
+
declare type RecoverParams = {
|
|
68
|
+
/** Wallet ID (can be v1 wallet or v2 wallet) */
|
|
69
|
+
walletId: string;
|
|
70
|
+
/** Coin to create the transaction for */
|
|
71
|
+
sourceCoin: AbstractUtxoCoin;
|
|
72
|
+
/** Coin that wallet keys were set up for */
|
|
73
|
+
recoveryCoin: AbstractUtxoCoin;
|
|
74
|
+
/** Source coin transaction to recover outputs from (sourceCoin) */
|
|
75
|
+
txid: string;
|
|
76
|
+
/** Source coin address to send the funds to */
|
|
77
|
+
recoveryAddress: string;
|
|
78
|
+
/** If set, decrypts private key and signs transaction */
|
|
79
|
+
walletPassphrase?: string;
|
|
80
|
+
/** If set, signs transaction */
|
|
81
|
+
xprv?: string;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Recover wallet deposits that were received on the wrong blockchain
|
|
85
|
+
* (for instance bitcoin deposits that were received for a litecoin wallet).
|
|
86
|
+
*
|
|
87
|
+
* Fetches the unspent data from BitGo's public blockchain API and the script data from the user's
|
|
88
|
+
* wallet.
|
|
89
|
+
*
|
|
90
|
+
* @param {BitGoBase} bitgo
|
|
91
|
+
* @param {RecoverParams} params
|
|
92
|
+
*/
|
|
93
|
+
export declare function recoverCrossChain(bitgo: BitGoBase, params: RecoverParams): Promise<CrossChainRecoverySigned | CrossChainRecoveryUnsigned>;
|
|
94
|
+
export {};
|
|
95
|
+
//# sourceMappingURL=crossChainRecovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crossChainRecovery.d.ts","sourceRoot":"","sources":["../../../src/recovery/crossChainRecovery.ts"],"names":[],"mappings":"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"}
|