@atomicfinance/bitcoin-wallet-provider 2.5.0 → 2.5.1
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/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-test.log +3 -0
- package/CHANGELOG.md +10 -0
- package/dist/BitcoinWalletProvider.d.ts +20 -0
- package/dist/BitcoinWalletProvider.js +191 -194
- package/dist/BitcoinWalletProvider.js.map +1 -1
- package/dist/index.d.ts +0 -0
- package/dist/index.js +9 -17
- package/dist/index.js.map +0 -0
- package/package.json +5 -6
- package/LICENSE +0 -674
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
3
13
|
});
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
function
|
|
12
|
-
return
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (obj != null) {
|
|
22
|
-
for(var key in obj){
|
|
23
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
24
|
-
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
|
|
25
|
-
if (desc.get || desc.set) {
|
|
26
|
-
Object.defineProperty(newObj, key, desc);
|
|
27
|
-
} else {
|
|
28
|
-
newObj[key] = obj[key];
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
newObj.default = obj;
|
|
34
|
-
return newObj;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
const provider_1 = __importDefault(require("@atomicfinance/provider"));
|
|
26
|
+
const types_1 = require("@atomicfinance/types");
|
|
27
|
+
const bitcoin_utils_1 = require("@liquality/bitcoin-utils");
|
|
28
|
+
const assert_1 = __importDefault(require("assert"));
|
|
29
|
+
const bitcoin = __importStar(require("bitcoinjs-lib"));
|
|
30
|
+
const secp256k1_1 = __importDefault(require("secp256k1"));
|
|
37
31
|
const FEE_PER_BYTE_FALLBACK = 5;
|
|
38
32
|
const ADDRESS_GAP = 20;
|
|
39
33
|
const NONCHANGE_ADDRESS = 0;
|
|
40
34
|
const CHANGE_ADDRESS = 1;
|
|
41
35
|
const NONCHANGE_OR_CHANGE_ADDRESS = 2;
|
|
42
|
-
|
|
36
|
+
class BitcoinWalletProvider extends provider_1.default {
|
|
37
|
+
constructor(network) {
|
|
38
|
+
super();
|
|
39
|
+
this._network = network;
|
|
40
|
+
this._unusedAddressesBlacklist = {};
|
|
41
|
+
this._maxAddressesToDerive = 5000;
|
|
42
|
+
}
|
|
43
43
|
async buildSweepTransactionWithSetOutputs(externalChangeAddress, feePerByte, _outputs, fixedInputs) {
|
|
44
44
|
return this._buildSweepTransaction(externalChangeAddress, feePerByte, _outputs, fixedInputs);
|
|
45
45
|
}
|
|
@@ -62,94 +62,90 @@ let BitcoinWalletProvider = class BitcoinWalletProvider extends _provider.defaul
|
|
|
62
62
|
// Create m-of-n multisig
|
|
63
63
|
const p2ms = bitcoin.payments.p2ms({
|
|
64
64
|
m: m,
|
|
65
|
-
pubkeys: pubkeys.map((key)=>Buffer.from(key, 'hex')
|
|
66
|
-
|
|
67
|
-
network: this._network
|
|
65
|
+
pubkeys: pubkeys.map((key) => Buffer.from(key, 'hex')),
|
|
66
|
+
network: this._network,
|
|
68
67
|
});
|
|
69
68
|
// Create p2wsh for multisig
|
|
70
69
|
const p2wsh = bitcoin.payments.p2wsh({
|
|
71
70
|
redeem: p2ms,
|
|
72
|
-
network: this._network
|
|
71
|
+
network: this._network,
|
|
73
72
|
});
|
|
74
73
|
return p2wsh;
|
|
75
74
|
}
|
|
76
75
|
/**
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
* Creates a native-segwit multi-signature address (P2MS in P2WSH) with n signatures of m required keys
|
|
77
|
+
* https://developer.bitcoin.org/reference/rpc/createmultisig.html
|
|
78
|
+
* @param m the number of required signatures
|
|
79
|
+
* @param pubkeys n possible pubkeys in total
|
|
80
|
+
* @returns a json object containing the `address` and `redeemScript`
|
|
81
|
+
*/
|
|
82
|
+
createMultisig(m, pubkeys) {
|
|
83
83
|
const p2wsh = this._createMultisigPayment(m, pubkeys);
|
|
84
84
|
return {
|
|
85
85
|
address: p2wsh.address,
|
|
86
|
-
redeemScript: p2wsh.redeem?.output?.toString('hex')
|
|
86
|
+
redeemScript: p2wsh.redeem?.output?.toString('hex'),
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
90
|
+
* Creates a PSBT of a native-segwit multi-signature address (P2MS in P2WSH) with n signatures of m required keys
|
|
91
|
+
* https://developer.bitcoin.org/reference/rpc/createmultisig.html
|
|
92
|
+
* https://developer.bitcoin.org/reference/rpc/createpsbt.html
|
|
93
|
+
* @param m the number of required signatures
|
|
94
|
+
* @param pubkeys n possible pubkeys in total
|
|
95
|
+
* @param inputs the Inputs to the PSBT
|
|
96
|
+
* @param ouputs the Outputs to the PSBT
|
|
97
|
+
* @returns a base64 encoded psbt string
|
|
98
|
+
*/
|
|
99
|
+
buildMultisigPSBT(m, pubkeys, inputs, outputs) {
|
|
100
|
+
assert_1.default(inputs.length > 0, 'no inputs found');
|
|
101
|
+
assert_1.default(outputs.length > 0, 'no outputs found');
|
|
101
102
|
const p2wsh = this._createMultisigPayment(m, pubkeys);
|
|
102
103
|
// Verify pubkeyhash for all inputs matches the p2wsh hash
|
|
103
|
-
|
|
104
|
-
), 'address pubkeyhash does not match input scriptPubKey');
|
|
104
|
+
assert_1.default(inputs.every((input) => p2wsh.output.toString('hex') === input.scriptPubKey), 'address pubkeyhash does not match input scriptPubKey');
|
|
105
105
|
// creator
|
|
106
|
-
const psbt = new bitcoin.Psbt({
|
|
107
|
-
network: this._network
|
|
108
|
-
});
|
|
106
|
+
const psbt = new bitcoin.Psbt({ network: this._network });
|
|
109
107
|
// updater
|
|
110
|
-
inputs.forEach((input)=>{
|
|
108
|
+
inputs.forEach((input) => {
|
|
111
109
|
psbt.addInput({
|
|
112
110
|
hash: input.txid,
|
|
113
111
|
index: input.vout,
|
|
114
|
-
witnessUtxo: {
|
|
115
|
-
|
|
116
|
-
value: input.value
|
|
117
|
-
},
|
|
118
|
-
witnessScript: p2wsh.redeem.output
|
|
112
|
+
witnessUtxo: { script: p2wsh.output, value: input.value },
|
|
113
|
+
witnessScript: p2wsh.redeem.output,
|
|
119
114
|
});
|
|
120
115
|
});
|
|
121
|
-
outputs.forEach((output)=>{
|
|
116
|
+
outputs.forEach((output) => {
|
|
122
117
|
psbt.addOutput({
|
|
123
118
|
address: output.to,
|
|
124
|
-
value: output.value
|
|
119
|
+
value: output.value,
|
|
125
120
|
});
|
|
126
121
|
});
|
|
127
122
|
return psbt.toBase64();
|
|
128
123
|
}
|
|
129
124
|
/**
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
125
|
+
* Update a PSBT with input information from our wallet and then sign inputs that we can sign for
|
|
126
|
+
* https://developer.bitcoin.org/reference/rpc/walletprocesspsbt.html
|
|
127
|
+
* @param psbt a base64 encoded psbt string (P2WSH only)
|
|
128
|
+
* @returns a base64 encoded signed psbt string
|
|
129
|
+
*/
|
|
130
|
+
async walletProcessPSBT(psbtString) {
|
|
135
131
|
const psbt = bitcoin.Psbt.fromBase64(psbtString);
|
|
136
|
-
await Promise.all(psbt.data.inputs.map(async (input, i)=>{
|
|
137
|
-
|
|
132
|
+
await Promise.all(psbt.data.inputs.map(async (input, i) => {
|
|
133
|
+
assert_1.default(psbt.getInputType(i).slice(0, 5) === 'p2wsh', 'only accepts P2WSH inputs');
|
|
138
134
|
const scriptStack = bitcoin.script.decompile(input.witnessScript);
|
|
139
|
-
const pubkeys = scriptStack.filter((data)=>Buffer.isBuffer(data) &&
|
|
140
|
-
)
|
|
141
|
-
await Promise.all(pubkeys.map(async (key)=>{
|
|
135
|
+
const pubkeys = scriptStack.filter((data) => Buffer.isBuffer(data) && secp256k1_1.default.publicKeyVerify(data));
|
|
136
|
+
await Promise.all(pubkeys.map(async (key) => {
|
|
142
137
|
// create address using pubkey
|
|
143
|
-
const { address: addressString
|
|
138
|
+
const { address: addressString } = bitcoin.payments.p2wpkh({
|
|
144
139
|
pubkey: key,
|
|
145
|
-
network: this._network
|
|
140
|
+
network: this._network,
|
|
146
141
|
});
|
|
147
142
|
// Retrieve address object from wallet using address
|
|
148
143
|
const address = await this.quickFindAddress([
|
|
149
|
-
addressString,
|
|
144
|
+
addressString,
|
|
150
145
|
]);
|
|
151
146
|
// exit if address doesn't exist in wallet
|
|
152
|
-
if (!address)
|
|
147
|
+
if (!address)
|
|
148
|
+
return;
|
|
153
149
|
// derive keypair
|
|
154
150
|
const keyPair = await this.getMethod('keyPair')(address.derivationPath);
|
|
155
151
|
// sign PSBT using keypair
|
|
@@ -160,76 +156,84 @@ let BitcoinWalletProvider = class BitcoinWalletProvider extends _provider.defaul
|
|
|
160
156
|
return psbt.toBase64();
|
|
161
157
|
}
|
|
162
158
|
/**
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
159
|
+
* Finalize the inputs of a PSBT. If the transaction is fully signed, it will
|
|
160
|
+
* produce a network serialized transaction which can be broadcast with sendrawtransaction
|
|
161
|
+
* https://developer.bitcoin.org/reference/rpc/finalizepsbt.html
|
|
162
|
+
* @param psbt a base64 encoded psbt string
|
|
163
|
+
* @returns a json object containing `psbt` in base64, `hex` for transaction and `complete` for if
|
|
164
|
+
* the transaction has a complete set of signatures
|
|
165
|
+
*/
|
|
166
|
+
finalizePSBT(psbtString) {
|
|
170
167
|
const psbt = bitcoin.Psbt.fromBase64(psbtString);
|
|
171
168
|
try {
|
|
172
169
|
psbt.validateSignaturesOfAllInputs(); // ensure all signatures are valid!
|
|
173
170
|
psbt.finalizeAllInputs();
|
|
174
|
-
}
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
175
173
|
return {
|
|
176
174
|
psbt: psbt.toBase64(),
|
|
177
|
-
complete: false
|
|
175
|
+
complete: false,
|
|
178
176
|
};
|
|
179
177
|
}
|
|
180
178
|
return {
|
|
181
179
|
psbt: psbt.toBase64(),
|
|
182
180
|
hex: psbt.extractTransaction().toHex(),
|
|
183
|
-
complete: true
|
|
181
|
+
complete: true,
|
|
184
182
|
};
|
|
185
183
|
}
|
|
186
184
|
async getUnusedAddress(change = false, numAddressPerCall = 100) {
|
|
187
185
|
const addressType = change ? CHANGE_ADDRESS : NONCHANGE_ADDRESS;
|
|
188
186
|
const key = change ? 'change' : 'nonChange';
|
|
189
|
-
const address = await this._getUsedUnusedAddresses(numAddressPerCall, addressType).then(({ unusedAddress
|
|
190
|
-
);
|
|
187
|
+
const address = await this._getUsedUnusedAddresses(numAddressPerCall, addressType).then(({ unusedAddress }) => unusedAddress[key]);
|
|
191
188
|
this._unusedAddressesBlacklist[address.address] = true;
|
|
192
189
|
return address;
|
|
193
190
|
}
|
|
194
191
|
async _getUsedUnusedAddresses(numAddressPerCall = 100, addressType) {
|
|
195
192
|
const usedAddresses = [];
|
|
196
|
-
const addressCountMap = {
|
|
197
|
-
|
|
198
|
-
nonChange: 0
|
|
199
|
-
};
|
|
200
|
-
const unusedAddressMap = {
|
|
201
|
-
change: null,
|
|
202
|
-
nonChange: null
|
|
203
|
-
};
|
|
193
|
+
const addressCountMap = { change: 0, nonChange: 0 };
|
|
194
|
+
const unusedAddressMap = { change: null, nonChange: null };
|
|
204
195
|
let addrList;
|
|
205
196
|
let addressIndex = 0;
|
|
206
197
|
let changeAddresses = [];
|
|
207
198
|
let nonChangeAddresses = [];
|
|
208
|
-
/* eslint-disable no-unmodified-loop-condition */
|
|
209
|
-
|
|
210
|
-
|
|
199
|
+
/* eslint-disable no-unmodified-loop-condition */
|
|
200
|
+
while ((addressType === NONCHANGE_OR_CHANGE_ADDRESS &&
|
|
201
|
+
(addressCountMap.change < ADDRESS_GAP ||
|
|
202
|
+
addressCountMap.nonChange < ADDRESS_GAP)) ||
|
|
203
|
+
(addressType === NONCHANGE_ADDRESS &&
|
|
204
|
+
addressCountMap.nonChange < ADDRESS_GAP) ||
|
|
205
|
+
(addressType === CHANGE_ADDRESS && addressCountMap.change < ADDRESS_GAP)) {
|
|
206
|
+
/* eslint-enable no-unmodified-loop-condition */
|
|
207
|
+
addrList = [];
|
|
208
|
+
if ((addressType === NONCHANGE_OR_CHANGE_ADDRESS ||
|
|
209
|
+
addressType === CHANGE_ADDRESS) &&
|
|
210
|
+
addressCountMap.change < ADDRESS_GAP) {
|
|
211
211
|
// Scanning for change addr
|
|
212
212
|
changeAddresses = await this.client.wallet.getAddresses(addressIndex, numAddressPerCall, true);
|
|
213
213
|
addrList = addrList.concat(changeAddresses);
|
|
214
|
-
}
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
215
216
|
changeAddresses = [];
|
|
216
217
|
}
|
|
217
|
-
if ((addressType === NONCHANGE_OR_CHANGE_ADDRESS ||
|
|
218
|
+
if ((addressType === NONCHANGE_OR_CHANGE_ADDRESS ||
|
|
219
|
+
addressType === NONCHANGE_ADDRESS) &&
|
|
220
|
+
addressCountMap.nonChange < ADDRESS_GAP) {
|
|
218
221
|
// Scanning for non change addr
|
|
219
222
|
nonChangeAddresses = await this.quickGetAddresses(addressIndex, numAddressPerCall, false);
|
|
220
223
|
addrList = addrList.concat(nonChangeAddresses);
|
|
221
224
|
}
|
|
222
225
|
const transactionCounts = await this.getMethod('getAddressTransactionCounts')(addrList);
|
|
223
|
-
for (const address of addrList){
|
|
224
|
-
const isUsed = transactionCounts[address.address] > 0 ||
|
|
225
|
-
|
|
226
|
-
);
|
|
226
|
+
for (const address of addrList) {
|
|
227
|
+
const isUsed = transactionCounts[address.address] > 0 ||
|
|
228
|
+
this._unusedAddressesBlacklist[address.address];
|
|
229
|
+
const isChangeAddress = changeAddresses.find((a) => address.address === a.address);
|
|
227
230
|
const key = isChangeAddress ? 'change' : 'nonChange';
|
|
228
231
|
if (isUsed) {
|
|
229
232
|
usedAddresses.push(address);
|
|
230
233
|
addressCountMap[key] = 0;
|
|
231
234
|
unusedAddressMap[key] = null;
|
|
232
|
-
}
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
233
237
|
addressCountMap[key]++;
|
|
234
238
|
if (!unusedAddressMap[key]) {
|
|
235
239
|
unusedAddressMap[key] = address;
|
|
@@ -239,23 +243,31 @@ let BitcoinWalletProvider = class BitcoinWalletProvider extends _provider.defaul
|
|
|
239
243
|
addressIndex += numAddressPerCall;
|
|
240
244
|
}
|
|
241
245
|
let firstUnusedAddress;
|
|
242
|
-
const indexNonChange = unusedAddressMap.nonChange
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
+
const indexNonChange = unusedAddressMap.nonChange
|
|
247
|
+
? unusedAddressMap.nonChange.index
|
|
248
|
+
: Infinity;
|
|
249
|
+
const indexChange = unusedAddressMap.change
|
|
250
|
+
? unusedAddressMap.change.index
|
|
251
|
+
: Infinity;
|
|
252
|
+
if (indexNonChange <= indexChange)
|
|
253
|
+
firstUnusedAddress = unusedAddressMap.nonChange;
|
|
254
|
+
else
|
|
255
|
+
firstUnusedAddress = unusedAddressMap.change;
|
|
246
256
|
return {
|
|
247
257
|
usedAddresses,
|
|
248
258
|
unusedAddress: unusedAddressMap,
|
|
249
|
-
firstUnusedAddress
|
|
259
|
+
firstUnusedAddress,
|
|
250
260
|
};
|
|
251
261
|
}
|
|
252
262
|
async sendSweepTransactionWithSetOutputs(externalChangeAddress, feePerByte, _outputs, fixedInputs) {
|
|
253
|
-
const { hex
|
|
263
|
+
const { hex, fee } = await this._buildSweepTransaction(externalChangeAddress, feePerByte, _outputs, fixedInputs);
|
|
254
264
|
await this.getMethod('sendRawTransaction')(hex);
|
|
255
|
-
return
|
|
265
|
+
return bitcoin_utils_1.normalizeTransactionObject(bitcoin_utils_1.decodeRawTransaction(hex, this._network), fee);
|
|
256
266
|
}
|
|
257
267
|
async _buildSweepTransaction(externalChangeAddress, feePerByte, _outputs = [], fixedInputs) {
|
|
258
|
-
const _feePerByte = feePerByte ||
|
|
268
|
+
const _feePerByte = feePerByte ||
|
|
269
|
+
(await this.getMethod('getFeePerByte')()) ||
|
|
270
|
+
FEE_PER_BYTE_FALLBACK;
|
|
259
271
|
const inputs = [];
|
|
260
272
|
const outputs = [];
|
|
261
273
|
try {
|
|
@@ -263,93 +275,85 @@ let BitcoinWalletProvider = class BitcoinWalletProvider extends _provider.defaul
|
|
|
263
275
|
if (inputsForAmount.change) {
|
|
264
276
|
throw Error('There should not be any change for sweeping transaction');
|
|
265
277
|
}
|
|
266
|
-
inputs.push(...inputsForAmount.inputs || []);
|
|
267
|
-
outputs.push(...inputsForAmount.outputs || []);
|
|
268
|
-
}
|
|
278
|
+
inputs.push(...(inputsForAmount.inputs || []));
|
|
279
|
+
outputs.push(...(inputsForAmount.outputs || []));
|
|
280
|
+
}
|
|
281
|
+
catch (e) {
|
|
269
282
|
if (fixedInputs.length === 0) {
|
|
270
283
|
throw Error(`Inputs for amount doesn't exist and no fixedInputs provided`);
|
|
271
284
|
}
|
|
272
285
|
const inputsForAmount = await this._getInputForAmountWithoutUtxoCheck(_outputs, _feePerByte, fixedInputs);
|
|
273
|
-
inputs.push(...inputsForAmount.inputs.map((utxo)=>
|
|
274
|
-
|
|
275
|
-
outputs.push(...inputsForAmount.outputs || []);
|
|
286
|
+
inputs.push(...(inputsForAmount.inputs.map((utxo) => types_1.Input.fromUTXO(utxo)) || []));
|
|
287
|
+
outputs.push(...(inputsForAmount.outputs || []));
|
|
276
288
|
}
|
|
277
|
-
_outputs.forEach((output)=>{
|
|
278
|
-
const spliceIndex = outputs.findIndex((sweepOutput)=>output.value === sweepOutput.value
|
|
279
|
-
);
|
|
289
|
+
_outputs.forEach((output) => {
|
|
290
|
+
const spliceIndex = outputs.findIndex((sweepOutput) => output.value === sweepOutput.value);
|
|
280
291
|
outputs.splice(spliceIndex, 1);
|
|
281
292
|
});
|
|
282
293
|
_outputs.push({
|
|
283
294
|
to: externalChangeAddress,
|
|
284
|
-
value: outputs[0].value
|
|
295
|
+
value: outputs[0].value,
|
|
285
296
|
});
|
|
286
297
|
return this._buildTransactionWithoutUtxoCheck(_outputs, _feePerByte, inputs);
|
|
287
298
|
}
|
|
288
299
|
_getInputForAmountWithoutUtxoCheck(_outputs, _feePerByte, fixedInputs) {
|
|
289
|
-
const utxoBalance = fixedInputs.reduce((a, b)=>a + (b['value'] || 0)
|
|
290
|
-
, 0);
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
})
|
|
298
|
-
);
|
|
300
|
+
const utxoBalance = fixedInputs.reduce((a, b) => a + (b['value'] || 0), 0);
|
|
301
|
+
const outputBalance = _outputs.reduce((a, b) => a + (b['value'] || 0), 0);
|
|
302
|
+
const amountToSend = utxoBalance -
|
|
303
|
+
_feePerByte * ((_outputs.length + 1) * 39 + fixedInputs.length * 153); // todo better calculation
|
|
304
|
+
const targets = _outputs.map((target, i) => ({
|
|
305
|
+
id: 'main',
|
|
306
|
+
value: target.value,
|
|
307
|
+
}));
|
|
299
308
|
if (amountToSend - outputBalance > 0) {
|
|
300
|
-
targets.push({
|
|
301
|
-
id: 'main',
|
|
302
|
-
value: amountToSend - outputBalance
|
|
303
|
-
});
|
|
309
|
+
targets.push({ id: 'main', value: amountToSend - outputBalance });
|
|
304
310
|
}
|
|
305
|
-
return
|
|
311
|
+
return bitcoin_utils_1.selectCoins(fixedInputs, targets, Math.ceil(_feePerByte), fixedInputs);
|
|
306
312
|
}
|
|
307
313
|
async _buildTransactionWithoutUtxoCheck(outputs, feePerByte, fixedInputs) {
|
|
308
314
|
const network = this._network;
|
|
309
|
-
const { fee
|
|
315
|
+
const { fee } = this._getInputForAmountWithoutUtxoCheck(outputs, feePerByte, fixedInputs);
|
|
310
316
|
const inputs = fixedInputs;
|
|
311
317
|
const txb = new bitcoin.TransactionBuilder(network);
|
|
312
|
-
for (const output of outputs){
|
|
318
|
+
for (const output of outputs) {
|
|
313
319
|
const to = output.to; // Allow for OP_RETURN
|
|
314
320
|
txb.addOutput(to, output.value);
|
|
315
321
|
}
|
|
316
322
|
const prevOutScriptType = 'p2wpkh';
|
|
317
|
-
for(let i = 0; i < inputs.length; i++){
|
|
323
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
318
324
|
const wallet = await this.getMethod('getWalletAddress')(inputs[i].address);
|
|
319
325
|
const keyPair = await this.getMethod('keyPair')(wallet.derivationPath);
|
|
320
326
|
const paymentVariant = this.getMethod('getPaymentVariantFromPublicKey')(keyPair.publicKey);
|
|
321
327
|
txb.addInput(inputs[i].txid, inputs[i].vout, 0, paymentVariant.output);
|
|
322
328
|
}
|
|
323
|
-
for(let
|
|
324
|
-
const wallet = await this.getMethod('getWalletAddress')(inputs[
|
|
329
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
330
|
+
const wallet = await this.getMethod('getWalletAddress')(inputs[i].address);
|
|
325
331
|
const keyPair = await this.getMethod('keyPair')(wallet.derivationPath);
|
|
326
332
|
const paymentVariant = this.getMethod('getPaymentVariantFromPublicKey')(keyPair.publicKey);
|
|
327
333
|
const needsWitness = true;
|
|
328
334
|
const signParams = {
|
|
329
335
|
prevOutScriptType,
|
|
330
|
-
vin:
|
|
336
|
+
vin: i,
|
|
331
337
|
keyPair,
|
|
332
|
-
witnessValue: 0
|
|
338
|
+
witnessValue: 0,
|
|
333
339
|
};
|
|
334
340
|
if (needsWitness) {
|
|
335
|
-
signParams.witnessValue = inputs[
|
|
341
|
+
signParams.witnessValue = inputs[i].value;
|
|
336
342
|
}
|
|
337
343
|
txb.sign(signParams);
|
|
338
344
|
}
|
|
339
|
-
return {
|
|
340
|
-
hex: txb.build().toHex(),
|
|
341
|
-
fee
|
|
342
|
-
};
|
|
345
|
+
return { hex: txb.build().toHex(), fee };
|
|
343
346
|
}
|
|
344
347
|
/**
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
348
|
+
* quickGetAddresses is an optimized version of getAddresses.
|
|
349
|
+
* It removes the call to `asyncSetImmediate()`, speeding up the function by a factor of 6x.
|
|
350
|
+
*
|
|
351
|
+
* @param startingIndex
|
|
352
|
+
* @param numAddresses
|
|
353
|
+
* @param change
|
|
354
|
+
* @returns {Promise<Address[]>}
|
|
355
|
+
*/
|
|
356
|
+
async quickGetAddresses(startingIndex = 0, numAddresses = 1, change = false) {
|
|
353
357
|
if (numAddresses < 1) {
|
|
354
358
|
throw new Error('You must return at least one address');
|
|
355
359
|
}
|
|
@@ -359,9 +363,10 @@ let BitcoinWalletProvider = class BitcoinWalletProvider extends _provider.defaul
|
|
|
359
363
|
// Original wallet provider is fetched to get the base derivation path
|
|
360
364
|
const originalProvider = this.client.getProviderForMethod('getAddresses');
|
|
361
365
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
362
|
-
const baseDerivationPath = originalProvider
|
|
366
|
+
const baseDerivationPath = originalProvider
|
|
367
|
+
._baseDerivationPath;
|
|
363
368
|
const getDerivationPathAddressFn = this.client.getMethod('getDerivationPathAddress');
|
|
364
|
-
for(let currentIndex = startingIndex; currentIndex < lastIndex; currentIndex++){
|
|
369
|
+
for (let currentIndex = startingIndex; currentIndex < lastIndex; currentIndex++) {
|
|
365
370
|
const subPath = changeVal + '/' + currentIndex;
|
|
366
371
|
const path = baseDerivationPath + '/' + subPath;
|
|
367
372
|
const addressObject = await getDerivationPathAddressFn(path);
|
|
@@ -370,28 +375,27 @@ let BitcoinWalletProvider = class BitcoinWalletProvider extends _provider.defaul
|
|
|
370
375
|
return addresses;
|
|
371
376
|
}
|
|
372
377
|
/**
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
378
|
+
* quickFindAddress is an optimized version of findAddress.
|
|
379
|
+
*
|
|
380
|
+
* It searches through both change and non-change addresses each iteration.
|
|
381
|
+
*
|
|
382
|
+
* This is in contrast to the original findAddress function which searches
|
|
383
|
+
* through all non-change addresses before moving on to change addresses.
|
|
384
|
+
*
|
|
385
|
+
* @param addresses
|
|
386
|
+
* @returns {Promise<Address[]>}
|
|
387
|
+
*/
|
|
388
|
+
async quickFindAddress(addresses) {
|
|
383
389
|
const addressesPerCall = 20;
|
|
384
390
|
let index = 0;
|
|
385
|
-
while(index < this._maxAddressesToDerive){
|
|
391
|
+
while (index < this._maxAddressesToDerive) {
|
|
386
392
|
const walletNonChangeAddresses = await this.quickGetAddresses(index, addressesPerCall, true);
|
|
387
393
|
const walletChangeAddresses = await this.quickGetAddresses(index, addressesPerCall, false);
|
|
388
394
|
const walletAddresses = [
|
|
389
395
|
...walletNonChangeAddresses,
|
|
390
|
-
...walletChangeAddresses,
|
|
396
|
+
...walletChangeAddresses,
|
|
391
397
|
];
|
|
392
|
-
const walletAddress = walletAddresses.find((walletAddr)=>addresses.find((addr)=>walletAddr.address === addr
|
|
393
|
-
)
|
|
394
|
-
);
|
|
398
|
+
const walletAddress = walletAddresses.find((walletAddr) => addresses.find((addr) => walletAddr.address === addr));
|
|
395
399
|
if (walletAddress) {
|
|
396
400
|
// Increment max addresses to derive by 100 if found within 100 addresses of maxAddressesToDerive
|
|
397
401
|
this._maxAddressesToDerive = Math.max(this._maxAddressesToDerive, index + 100);
|
|
@@ -400,13 +404,6 @@ let BitcoinWalletProvider = class BitcoinWalletProvider extends _provider.defaul
|
|
|
400
404
|
index += addressesPerCall;
|
|
401
405
|
}
|
|
402
406
|
}
|
|
403
|
-
|
|
404
|
-
super();
|
|
405
|
-
this._network = network;
|
|
406
|
-
this._unusedAddressesBlacklist = {};
|
|
407
|
-
this._maxAddressesToDerive = 5000;
|
|
408
|
-
}
|
|
409
|
-
};
|
|
407
|
+
}
|
|
410
408
|
exports.default = BitcoinWalletProvider;
|
|
411
|
-
|
|
412
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9CaXRjb2luV2FsbGV0UHJvdmlkZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFByb3ZpZGVyIGZyb20gJ0BhdG9taWNmaW5hbmNlL3Byb3ZpZGVyJztcbmltcG9ydCB7XG4gIENyZWF0ZU11bHRpc2lnUmVzcG9uc2UsXG4gIGZpbmFsaXplUFNCVFJlc3BvbnNlLFxuICBGaW5hbmNlV2FsbGV0UHJvdmlkZXIsXG4gIElucHV0LFxuICBPdXRwdXQsXG59IGZyb20gJ0BhdG9taWNmaW5hbmNlL3R5cGVzJztcbmltcG9ydCB7IEJpdGNvaW5OZXR3b3JrIH0gZnJvbSAnQGxpcXVhbGl0eS9iaXRjb2luLW5ldHdvcmtzJztcbmltcG9ydCB7XG4gIGRlY29kZVJhd1RyYW5zYWN0aW9uLFxuICBub3JtYWxpemVUcmFuc2FjdGlvbk9iamVjdCxcbiAgc2VsZWN0Q29pbnMsXG59IGZyb20gJ0BsaXF1YWxpdHkvYml0Y29pbi11dGlscyc7XG5pbXBvcnQgeyBBZGRyZXNzLCBiaXRjb2luIGFzIGJULCBUcmFuc2FjdGlvbiB9IGZyb20gJ0BsaXF1YWxpdHkvdHlwZXMnO1xuaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0ICogYXMgYml0Y29pbiBmcm9tICdiaXRjb2luanMtbGliJztcbmltcG9ydCBzZWNwMjU2azEgZnJvbSAnc2VjcDI1NmsxJztcblxuY29uc3QgRkVFX1BFUl9CWVRFX0ZBTExCQUNLID0gNTtcbmNvbnN0IEFERFJFU1NfR0FQID0gMjA7XG5jb25zdCBOT05DSEFOR0VfQUREUkVTUyA9IDA7XG5jb25zdCBDSEFOR0VfQUREUkVTUyA9IDE7XG5jb25zdCBOT05DSEFOR0VfT1JfQ0hBTkdFX0FERFJFU1MgPSAyO1xuXG50eXBlIFVudXNlZEFkZHJlc3Nlc0JsYWNrbGlzdCA9IHtcbiAgW2FkZHJlc3M6IHN0cmluZ106IHRydWU7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCaXRjb2luV2FsbGV0UHJvdmlkZXJcbiAgZXh0ZW5kcyBQcm92aWRlclxuICBpbXBsZW1lbnRzIFBhcnRpYWw8RmluYW5jZVdhbGxldFByb3ZpZGVyPiB7XG4gIF9uZXR3b3JrOiBCaXRjb2luTmV0d29yaztcbiAgX3VudXNlZEFkZHJlc3Nlc0JsYWNrbGlzdDogVW51c2VkQWRkcmVzc2VzQmxhY2tsaXN0O1xuICBfbWF4QWRkcmVzc2VzVG9EZXJpdmU6IG51bWJlcjtcblxuICBjb25zdHJ1Y3RvcihuZXR3b3JrOiBCaXRjb2luTmV0d29yaykge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9uZXR3b3JrID0gbmV0d29yaztcbiAgICB0aGlzLl91bnVzZWRBZGRyZXNzZXNCbGFja2xpc3QgPSB7fTtcbiAgICB0aGlzLl9tYXhBZGRyZXNzZXNUb0Rlcml2ZSA9IDUwMDA7XG4gIH1cblxuICBhc3luYyBidWlsZFN3ZWVwVHJhbnNhY3Rpb25XaXRoU2V0T3V0cHV0cyhcbiAgICBleHRlcm5hbENoYW5nZUFkZHJlc3M6IHN0cmluZyxcbiAgICBmZWVQZXJCeXRlOiBudW1iZXIsXG4gICAgX291dHB1dHM6IE91dHB1dFtdLFxuICAgIGZpeGVkSW5wdXRzOiBJbnB1dFtdLFxuICApIHtcbiAgICByZXR1cm4gdGhpcy5fYnVpbGRTd2VlcFRyYW5zYWN0aW9uKFxuICAgICAgZXh0ZXJuYWxDaGFuZ2VBZGRyZXNzLFxuICAgICAgZmVlUGVyQnl0ZSxcbiAgICAgIF9vdXRwdXRzLFxuICAgICAgZml4ZWRJbnB1dHMsXG4gICAgKTtcbiAgfVxuXG4gIGdldFVudXNlZEFkZHJlc3Nlc0JsYWNrbGlzdCgpOiBVbnVzZWRBZGRyZXNzZXNCbGFja2xpc3Qge1xuICAgIHJldHVybiB0aGlzLl91bnVzZWRBZGRyZXNzZXNCbGFja2xpc3Q7XG4gIH1cblxuICBzZXRVbnVzZWRBZGRyZXNzZXNCbGFja2xpc3QoXG4gICAgdW51c2VkQWRkcmVzc2VzQmxhY2tsaXN0OiBVbnVzZWRBZGRyZXNzZXNCbGFja2xpc3QsXG4gICkge1xuICAgIHRoaXMuX3VudXNlZEFkZHJlc3Nlc0JsYWNrbGlzdCA9IHVudXNlZEFkZHJlc3Nlc0JsYWNrbGlzdDtcbiAgfVxuXG4gIHNldE1heEFkZHJlc3Nlc1RvRGVyaXZlKG1heEFkZHJlc3Nlc1RvRGVyaXZlOiBudW1iZXIpIHtcbiAgICB0aGlzLl9tYXhBZGRyZXNzZXNUb0Rlcml2ZSA9IG1heEFkZHJlc3Nlc1RvRGVyaXZlO1xuICB9XG5cbiAgZ2V0TWF4QWRkcmVzc2VzVG9EZXJpdmUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX21heEFkZHJlc3Nlc1RvRGVyaXZlO1xuICB9XG5cbiAgX2NyZWF0ZU11bHRpc2lnUGF5bWVudChtOiBudW1iZXIsIHB1YmtleXM6IHN0cmluZ1tdKTogYml0Y29pbi5QYXltZW50IHtcbiAgICBpZiAobSA+IHB1YmtleXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBub3QgZW5vdWdoIGtleXMgc3VwcGxpZWQgKGdvdCAke3B1YmtleXMubGVuZ3RofSBrZXlzLCBidXQgbmVlZCBhdCBsZWFzdCAke219IHRvIHJlZGVlbSlgLFxuICAgICAgKTtcbiAgICB9XG4gICAgLy8gQ3JlYXRlIG0tb2YtbiBtdWx0aXNpZ1xuICAgIGNvbnN0IHAybXMgPSBiaXRjb2luLnBheW1lbnRzLnAybXMoe1xuICAgICAgbTogbSxcbiAgICAgIHB1YmtleXM6IHB1YmtleXMubWFwKChrZXk6IHN0cmluZykgPT4gQnVmZmVyLmZyb20oa2V5LCAnaGV4JykpLFxuICAgICAgbmV0d29yazogdGhpcy5fbmV0d29yayxcbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBwMndzaCBmb3IgbXVsdGlzaWdcbiAgICBjb25zdCBwMndzaCA9IGJpdGNvaW4ucGF5bWVudHMucDJ3c2goe1xuICAgICAgcmVkZWVtOiBwMm1zLFxuICAgICAgbmV0d29yazogdGhpcy5fbmV0d29yayxcbiAgICB9KTtcblxuICAgIHJldHVybiBwMndzaDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmF0aXZlLXNlZ3dpdCBtdWx0aS1zaWduYXR1cmUgYWRkcmVzcyAoUDJNUyBpbiBQMldTSCkgd2l0aCBuIHNpZ25hdHVyZXMgb2YgbSByZXF1aXJlZCBrZXlzXG4gICAqIGh0dHBzOi8vZGV2ZWxvcGVyLmJpdGNvaW4ub3JnL3JlZmVyZW5jZS9ycGMvY3JlYXRlbXVsdGlzaWcuaHRtbFxuICAgKiBAcGFyYW0gbSB0aGUgbnVtYmVyIG9mIHJlcXVpcmVkIHNpZ25hdHVyZXNcbiAgICogQHBhcmFtIHB1YmtleXMgbiBwb3NzaWJsZSBwdWJrZXlzIGluIHRvdGFsXG4gICAqIEByZXR1cm5zIGEganNvbiBvYmplY3QgY29udGFpbmluZyB0aGUgYGFkZHJlc3NgIGFuZCBgcmVkZWVtU2NyaXB0YFxuICAgKi9cbiAgY3JlYXRlTXVsdGlzaWcobTogbnVtYmVyLCBwdWJrZXlzOiBzdHJpbmdbXSk6IENyZWF0ZU11bHRpc2lnUmVzcG9uc2Uge1xuICAgIGNvbnN0IHAyd3NoID0gdGhpcy5fY3JlYXRlTXVsdGlzaWdQYXltZW50KG0sIHB1YmtleXMpO1xuICAgIHJldHVybiB7XG4gICAgICBhZGRyZXNzOiBwMndzaC5hZGRyZXNzLFxuICAgICAgcmVkZWVtU2NyaXB0OiBwMndzaC5yZWRlZW0/Lm91dHB1dD8udG9TdHJpbmcoJ2hleCcpLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIFBTQlQgb2YgYSBuYXRpdmUtc2Vnd2l0IG11bHRpLXNpZ25hdHVyZSBhZGRyZXNzIChQMk1TIGluIFAyV1NIKSB3aXRoIG4gc2lnbmF0dXJlcyBvZiBtIHJlcXVpcmVkIGtleXNcbiAgICogaHR0cHM6Ly9kZXZlbG9wZXIuYml0Y29pbi5vcmcvcmVmZXJlbmNlL3JwYy9jcmVhdGVtdWx0aXNpZy5odG1sXG4gICAqIGh0dHBzOi8vZGV2ZWxvcGVyLmJpdGNvaW4ub3JnL3JlZmVyZW5jZS9ycGMvY3JlYXRlcHNidC5odG1sXG4gICAqIEBwYXJhbSBtIHRoZSBudW1iZXIgb2YgcmVxdWlyZWQgc2lnbmF0dXJlc1xuICAgKiBAcGFyYW0gcHVia2V5cyBuIHBvc3NpYmxlIHB1YmtleXMgaW4gdG90YWxcbiAgICogQHBhcmFtIGlucHV0cyB0aGUgSW5wdXRzIHRvIHRoZSBQU0JUXG4gICAqIEBwYXJhbSBvdXB1dHMgdGhlIE91dHB1dHMgdG8gdGhlIFBTQlRcbiAgICogQHJldHVybnMgYSBiYXNlNjQgZW5jb2RlZCBwc2J0IHN0cmluZ1xuICAgKi9cbiAgYnVpbGRNdWx0aXNpZ1BTQlQoXG4gICAgbTogbnVtYmVyLFxuICAgIHB1YmtleXM6IHN0cmluZ1tdLFxuICAgIGlucHV0czogSW5wdXRbXSxcbiAgICBvdXRwdXRzOiBPdXRwdXRbXSxcbiAgKTogc3RyaW5nIHtcbiAgICBhc3NlcnQoaW5wdXRzLmxlbmd0aCA+IDAsICdubyBpbnB1dHMgZm91bmQnKTtcbiAgICBhc3NlcnQob3V0cHV0cy5sZW5ndGggPiAwLCAnbm8gb3V0cHV0cyBmb3VuZCcpO1xuXG4gICAgY29uc3QgcDJ3c2ggPSB0aGlzLl9jcmVhdGVNdWx0aXNpZ1BheW1lbnQobSwgcHVia2V5cyk7XG5cbiAgICAvLyBWZXJpZnkgcHVia2V5aGFzaCBmb3IgYWxsIGlucHV0cyBtYXRjaGVzIHRoZSBwMndzaCBoYXNoXG4gICAgYXNzZXJ0KFxuICAgICAgaW5wdXRzLmV2ZXJ5KFxuICAgICAgICAoaW5wdXQ6IElucHV0KSA9PiBwMndzaC5vdXRwdXQudG9TdHJpbmcoJ2hleCcpID09PSBpbnB1dC5zY3JpcHRQdWJLZXksXG4gICAgICApLFxuICAgICAgJ2FkZHJlc3MgcHVia2V5aGFzaCBkb2VzIG5vdCBtYXRjaCBpbnB1dCBzY3JpcHRQdWJLZXknLFxuICAgICk7XG5cbiAgICAvLyBjcmVhdG9yXG4gICAgY29uc3QgcHNidCA9IG5ldyBiaXRjb2luLlBzYnQoeyBuZXR3b3JrOiB0aGlzLl9uZXR3b3JrIH0pO1xuXG4gICAgLy8gdXBkYXRlclxuICAgIGlucHV0cy5mb3JFYWNoKChpbnB1dDogSW5wdXQpID0+IHtcbiAgICAgIHBzYnQuYWRkSW5wdXQoe1xuICAgICAgICBoYXNoOiBpbnB1dC50eGlkLFxuICAgICAgICBpbmRleDogaW5wdXQudm91dCxcbiAgICAgICAgd2l0bmVzc1V0eG86IHsgc2NyaXB0OiBwMndzaC5vdXRwdXQsIHZhbHVlOiBpbnB1dC52YWx1ZSB9LFxuICAgICAgICB3aXRuZXNzU2NyaXB0OiBwMndzaC5yZWRlZW0ub3V0cHV0LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBvdXRwdXRzLmZvckVhY2goKG91dHB1dDogT3V0cHV0KSA9PiB7XG4gICAgICBwc2J0LmFkZE91dHB1dCh7XG4gICAgICAgIGFkZHJlc3M6IG91dHB1dC50byxcbiAgICAgICAgdmFsdWU6IG91dHB1dC52YWx1ZSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHBzYnQudG9CYXNlNjQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgYSBQU0JUIHdpdGggaW5wdXQgaW5mb3JtYXRpb24gZnJvbSBvdXIgd2FsbGV0IGFuZCB0aGVuIHNpZ24gaW5wdXRzIHRoYXQgd2UgY2FuIHNpZ24gZm9yXG4gICAqIGh0dHBzOi8vZGV2ZWxvcGVyLmJpdGNvaW4ub3JnL3JlZmVyZW5jZS9ycGMvd2FsbGV0cHJvY2Vzc3BzYnQuaHRtbFxuICAgKiBAcGFyYW0gcHNidCBhIGJhc2U2NCBlbmNvZGVkIHBzYnQgc3RyaW5nIChQMldTSCBvbmx5KVxuICAgKiBAcmV0dXJucyBhIGJhc2U2NCBlbmNvZGVkIHNpZ25lZCBwc2J0IHN0cmluZ1xuICAgKi9cbiAgYXN5bmMgd2FsbGV0UHJvY2Vzc1BTQlQocHNidFN0cmluZzogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBwc2J0ID0gYml0Y29pbi5Qc2J0LmZyb21CYXNlNjQocHNidFN0cmluZyk7XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHBzYnQuZGF0YS5pbnB1dHMubWFwKGFzeW5jIChpbnB1dCwgaTogbnVtYmVyKSA9PiB7XG4gICAgICAgIGFzc2VydChcbiAgICAgICAgICBwc2J0LmdldElucHV0VHlwZShpKS5zbGljZSgwLCA1KSA9PT0gJ3Ayd3NoJyxcbiAgICAgICAgICAnb25seSBhY2NlcHRzIFAyV1NIIGlucHV0cycsXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3Qgc2NyaXB0U3RhY2sgPSBiaXRjb2luLnNjcmlwdC5kZWNvbXBpbGUoaW5wdXQud2l0bmVzc1NjcmlwdCk7XG4gICAgICAgIGNvbnN0IHB1YmtleXMgPSBzY3JpcHRTdGFjay5maWx0ZXIoXG4gICAgICAgICAgKGRhdGEpID0+IEJ1ZmZlci5pc0J1ZmZlcihkYXRhKSAmJiBzZWNwMjU2azEucHVibGljS2V5VmVyaWZ5KGRhdGEpLFxuICAgICAgICApO1xuXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgIHB1YmtleXMubWFwKGFzeW5jIChrZXkpID0+IHtcbiAgICAgICAgICAgIC8vIGNyZWF0ZSBhZGRyZXNzIHVzaW5nIHB1YmtleVxuICAgICAgICAgICAgY29uc3QgeyBhZGRyZXNzOiBhZGRyZXNzU3RyaW5nIH0gPSBiaXRjb2luLnBheW1lbnRzLnAyd3BraCh7XG4gICAgICAgICAgICAgIHB1YmtleToga2V5IGFzIEJ1ZmZlcixcbiAgICAgICAgICAgICAgbmV0d29yazogdGhpcy5fbmV0d29yayxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBSZXRyaWV2ZSBhZGRyZXNzIG9iamVjdCBmcm9tIHdhbGxldCB1c2luZyBhZGRyZXNzXG4gICAgICAgICAgICBjb25zdCBhZGRyZXNzOiBBZGRyZXNzID0gYXdhaXQgdGhpcy5xdWlja0ZpbmRBZGRyZXNzKFtcbiAgICAgICAgICAgICAgYWRkcmVzc1N0cmluZyxcbiAgICAgICAgICAgIF0pO1xuXG4gICAgICAgICAgICAvLyBleGl0IGlmIGFkZHJlc3MgZG9lc24ndCBleGlzdCBpbiB3YWxsZXRcbiAgICAgICAgICAgIGlmICghYWRkcmVzcykgcmV0dXJuO1xuXG4gICAgICAgICAgICAvLyBkZXJpdmUga2V5cGFpclxuICAgICAgICAgICAgY29uc3Qga2V5UGFpciA9IGF3YWl0IHRoaXMuZ2V0TWV0aG9kKCdrZXlQYWlyJykoXG4gICAgICAgICAgICAgIGFkZHJlc3MuZGVyaXZhdGlvblBhdGgsXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvLyBzaWduIFBTQlQgdXNpbmcga2V5cGFpclxuICAgICAgICAgICAgcHNidC5zaWduSW5wdXQoaSwga2V5UGFpcik7XG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgcHNidC52YWxpZGF0ZVNpZ25hdHVyZXNPZkFsbElucHV0cygpOyAvLyBlbnN1cmUgYWxsIHNpZ25hdHVyZXMgYXJlIHZhbGlkIVxuICAgIHJldHVybiBwc2J0LnRvQmFzZTY0KCk7XG4gIH1cblxuICAvKipcbiAgICogRmluYWxpemUgdGhlIGlucHV0cyBvZiBhIFBTQlQuIElmIHRoZSB0cmFuc2FjdGlvbiBpcyBmdWxseSBzaWduZWQsIGl0IHdpbGxcbiAgICogcHJvZHVjZSBhIG5ldHdvcmsgc2VyaWFsaXplZCB0cmFuc2FjdGlvbiB3aGljaCBjYW4gYmUgYnJvYWRjYXN0IHdpdGggc2VuZHJhd3RyYW5zYWN0aW9uXG4gICAqIGh0dHBzOi8vZGV2ZWxvcGVyLmJpdGNvaW4ub3JnL3JlZmVyZW5jZS9ycGMvZmluYWxpemVwc2J0Lmh0bWxcbiAgICogQHBhcmFtIHBzYnQgYSBiYXNlNjQgZW5jb2RlZCBwc2J0IHN0cmluZ1xuICAgKiBAcmV0dXJucyBhIGpzb24gb2JqZWN0IGNvbnRhaW5pbmcgYHBzYnRgIGluIGJhc2U2NCwgYGhleGAgZm9yIHRyYW5zYWN0aW9uIGFuZCBgY29tcGxldGVgIGZvciBpZlxuICAgKiB0aGUgdHJhbnNhY3Rpb24gaGFzIGEgY29tcGxldGUgc2V0IG9mIHNpZ25hdHVyZXNcbiAgICovXG4gIGZpbmFsaXplUFNCVChwc2J0U3RyaW5nOiBzdHJpbmcpOiBmaW5hbGl6ZVBTQlRSZXNwb25zZSB7XG4gICAgY29uc3QgcHNidCA9IGJpdGNvaW4uUHNidC5mcm9tQmFzZTY0KHBzYnRTdHJpbmcpO1xuXG4gICAgdHJ5IHtcbiAgICAgIHBzYnQudmFsaWRhdGVTaWduYXR1cmVzT2ZBbGxJbnB1dHMoKTsgLy8gZW5zdXJlIGFsbCBzaWduYXR1cmVzIGFyZSB2YWxpZCFcbiAgICAgIHBzYnQuZmluYWxpemVBbGxJbnB1dHMoKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcHNidDogcHNidC50b0Jhc2U2NCgpLFxuICAgICAgICBjb21wbGV0ZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgcHNidDogcHNidC50b0Jhc2U2NCgpLFxuICAgICAgaGV4OiBwc2J0LmV4dHJhY3RUcmFuc2FjdGlvbigpLnRvSGV4KCksXG4gICAgICBjb21wbGV0ZTogdHJ1ZSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZ2V0VW51c2VkQWRkcmVzcyhjaGFuZ2UgPSBmYWxzZSwgbnVtQWRkcmVzc1BlckNhbGwgPSAxMDApIHtcbiAgICBjb25zdCBhZGRyZXNzVHlwZSA9IGNoYW5nZSA/IENIQU5HRV9BRERSRVNTIDogTk9OQ0hBTkdFX0FERFJFU1M7XG4gICAgY29uc3Qga2V5ID0gY2hhbmdlID8gJ2NoYW5nZScgOiAnbm9uQ2hhbmdlJztcblxuICAgIGNvbnN0IGFkZHJlc3MgPSBhd2FpdCB0aGlzLl9nZXRVc2VkVW51c2VkQWRkcmVzc2VzKFxuICAgICAgbnVtQWRkcmVzc1BlckNhbGwsXG4gICAgICBhZGRyZXNzVHlwZSxcbiAgICApLnRoZW4oKHsgdW51c2VkQWRkcmVzcyB9KSA9PiB1bnVzZWRBZGRyZXNzW2tleV0pO1xuICAgIHRoaXMuX3VudXNlZEFkZHJlc3Nlc0JsYWNrbGlzdFthZGRyZXNzLmFkZHJlc3NdID0gdHJ1ZTtcblxuICAgIHJldHVybiBhZGRyZXNzO1xuICB9XG5cbiAgYXN5bmMgX2dldFVzZWRVbnVzZWRBZGRyZXNzZXMobnVtQWRkcmVzc1BlckNhbGwgPSAxMDAsIGFkZHJlc3NUeXBlKSB7XG4gICAgY29uc3QgdXNlZEFkZHJlc3NlcyA9IFtdO1xuICAgIGNvbnN0IGFkZHJlc3NDb3VudE1hcCA9IHsgY2hhbmdlOiAwLCBub25DaGFuZ2U6IDAgfTtcbiAgICBjb25zdCB1bnVzZWRBZGRyZXNzTWFwID0geyBjaGFuZ2U6IG51bGwsIG5vbkNoYW5nZTogbnVsbCB9O1xuXG4gICAgbGV0IGFkZHJMaXN0O1xuICAgIGxldCBhZGRyZXNzSW5kZXggPSAwO1xuICAgIGxldCBjaGFuZ2VBZGRyZXNzZXM6IEFkZHJlc3NbXSA9IFtdO1xuICAgIGxldCBub25DaGFuZ2VBZGRyZXNzZXM6IEFkZHJlc3NbXSA9IFtdO1xuXG4gICAgLyogZXNsaW50LWRpc2FibGUgbm8tdW5tb2RpZmllZC1sb29wLWNvbmRpdGlvbiAqL1xuICAgIHdoaWxlIChcbiAgICAgIChhZGRyZXNzVHlwZSA9PT0gTk9OQ0hBTkdFX09SX0NIQU5HRV9BRERSRVNTICYmXG4gICAgICAgIChhZGRyZXNzQ291bnRNYXAuY2hhbmdlIDwgQUREUkVTU19HQVAgfHxcbiAgICAgICAgICBhZGRyZXNzQ291bnRNYXAubm9uQ2hhbmdlIDwgQUREUkVTU19HQVApKSB8fFxuICAgICAgKGFkZHJlc3NUeXBlID09PSBOT05DSEFOR0VfQUREUkVTUyAmJlxuICAgICAgICBhZGRyZXNzQ291bnRNYXAubm9uQ2hhbmdlIDwgQUREUkVTU19HQVApIHx8XG4gICAgICAoYWRkcmVzc1R5cGUgPT09IENIQU5HRV9BRERSRVNTICYmIGFkZHJlc3NDb3VudE1hcC5jaGFuZ2UgPCBBRERSRVNTX0dBUClcbiAgICApIHtcbiAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tdW5tb2RpZmllZC1sb29wLWNvbmRpdGlvbiAqL1xuICAgICAgYWRkckxpc3QgPSBbXTtcblxuICAgICAgaWYgKFxuICAgICAgICAoYWRkcmVzc1R5cGUgPT09IE5PTkNIQU5HRV9PUl9DSEFOR0VfQUREUkVTUyB8fFxuICAgICAgICAgIGFkZHJlc3NUeXBlID09PSBDSEFOR0VfQUREUkVTUykgJiZcbiAgICAgICAgYWRkcmVzc0NvdW50TWFwLmNoYW5nZSA8IEFERFJFU1NfR0FQXG4gICAgICApIHtcbiAgICAgICAgLy8gU2Nhbm5pbmcgZm9yIGNoYW5nZSBhZGRyXG4gICAgICAgIGNoYW5nZUFkZHJlc3NlcyA9IGF3YWl0IHRoaXMuY2xpZW50LndhbGxldC5nZXRBZGRyZXNzZXMoXG4gICAgICAgICAgYWRkcmVzc0luZGV4LFxuICAgICAgICAgIG51bUFkZHJlc3NQZXJDYWxsLFxuICAgICAgICAgIHRydWUsXG4gICAgICAgICk7XG4gICAgICAgIGFkZHJMaXN0ID0gYWRkckxpc3QuY29uY2F0KGNoYW5nZUFkZHJlc3Nlcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGFuZ2VBZGRyZXNzZXMgPSBbXTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICAoYWRkcmVzc1R5cGUgPT09IE5PTkNIQU5HRV9PUl9DSEFOR0VfQUREUkVTUyB8fFxuICAgICAgICAgIGFkZHJlc3NUeXBlID09PSBOT05DSEFOR0VfQUREUkVTUykgJiZcbiAgICAgICAgYWRkcmVzc0NvdW50TWFwLm5vbkNoYW5nZSA8IEFERFJFU1NfR0FQXG4gICAgICApIHtcbiAgICAgICAgLy8gU2Nhbm5pbmcgZm9yIG5vbiBjaGFuZ2UgYWRkclxuICAgICAgICBub25DaGFuZ2VBZGRyZXNzZXMgPSBhd2FpdCB0aGlzLnF1aWNrR2V0QWRkcmVzc2VzKFxuICAgICAgICAgIGFkZHJlc3NJbmRleCxcbiAgICAgICAgICBudW1BZGRyZXNzUGVyQ2FsbCxcbiAgICAgICAgICBmYWxzZSxcbiAgICAgICAgKTtcbiAgICAgICAgYWRkckxpc3QgPSBhZGRyTGlzdC5jb25jYXQobm9uQ2hhbmdlQWRkcmVzc2VzKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb25Db3VudHMgPSBhd2FpdCB0aGlzLmdldE1ldGhvZChcbiAgICAgICAgJ2dldEFkZHJlc3NUcmFuc2FjdGlvbkNvdW50cycsXG4gICAgICApKGFkZHJMaXN0KTtcblxuICAgICAgZm9yIChjb25zdCBhZGRyZXNzIG9mIGFkZHJMaXN0KSB7XG4gICAgICAgIGNvbnN0IGlzVXNlZCA9XG4gICAgICAgICAgdHJhbnNhY3Rpb25Db3VudHNbYWRkcmVzcy5hZGRyZXNzXSA+IDAgfHxcbiAgICAgICAgICB0aGlzLl91bnVzZWRBZGRyZXNzZXNCbGFja2xpc3RbYWRkcmVzcy5hZGRyZXNzXTtcbiAgICAgICAgY29uc3QgaXNDaGFuZ2VBZGRyZXNzID0gY2hhbmdlQWRkcmVzc2VzLmZpbmQoXG4gICAgICAgICAgKGEpID0+IGFkZHJlc3MuYWRkcmVzcyA9PT0gYS5hZGRyZXNzLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBrZXkgPSBpc0NoYW5nZUFkZHJlc3MgPyAnY2hhbmdlJyA6ICdub25DaGFuZ2UnO1xuXG4gICAgICAgIGlmIChpc1VzZWQpIHtcbiAgICAgICAgICB1c2VkQWRkcmVzc2VzLnB1c2goYWRkcmVzcyk7XG4gICAgICAgICAgYWRkcmVzc0NvdW50TWFwW2tleV0gPSAwO1xuICAgICAgICAgIHVudXNlZEFkZHJlc3NNYXBba2V5XSA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYWRkcmVzc0NvdW50TWFwW2tleV0rKztcblxuICAgICAgICAgIGlmICghdW51c2VkQWRkcmVzc01hcFtrZXldKSB7XG4gICAgICAgICAgICB1bnVzZWRBZGRyZXNzTWFwW2tleV0gPSBhZGRyZXNzO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBhZGRyZXNzSW5kZXggKz0gbnVtQWRkcmVzc1BlckNhbGw7XG4gICAgfVxuXG4gICAgbGV0IGZpcnN0VW51c2VkQWRkcmVzcztcbiAgICBjb25zdCBpbmRleE5vbkNoYW5nZSA9IHVudXNlZEFkZHJlc3NNYXAubm9uQ2hhbmdlXG4gICAgICA/IHVudXNlZEFkZHJlc3NNYXAubm9uQ2hhbmdlLmluZGV4XG4gICAgICA6IEluZmluaXR5O1xuICAgIGNvbnN0IGluZGV4Q2hhbmdlID0gdW51c2VkQWRkcmVzc01hcC5jaGFuZ2VcbiAgICAgID8gdW51c2VkQWRkcmVzc01hcC5jaGFuZ2UuaW5kZXhcbiAgICAgIDogSW5maW5pdHk7XG5cbiAgICBpZiAoaW5kZXhOb25DaGFuZ2UgPD0gaW5kZXhDaGFuZ2UpXG4gICAgICBmaXJzdFVudXNlZEFkZHJlc3MgPSB1bnVzZWRBZGRyZXNzTWFwLm5vbkNoYW5nZTtcbiAgICBlbHNlIGZpcnN0VW51c2VkQWRkcmVzcyA9IHVudXNlZEFkZHJlc3NNYXAuY2hhbmdlO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHVzZWRBZGRyZXNzZXMsXG4gICAgICB1bnVzZWRBZGRyZXNzOiB1bnVzZWRBZGRyZXNzTWFwLFxuICAgICAgZmlyc3RVbnVzZWRBZGRyZXNzLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBzZW5kU3dlZXBUcmFuc2FjdGlvbldpdGhTZXRPdXRwdXRzKFxuICAgIGV4dGVybmFsQ2hhbmdlQWRkcmVzczogc3RyaW5nLFxuICAgIGZlZVBlckJ5dGU6IG51bWJlcixcbiAgICBfb3V0cHV0czogT3V0cHV0W10sXG4gICAgZml4ZWRJbnB1dHM6IElucHV0W10sXG4gICk6IFByb21pc2U8VHJhbnNhY3Rpb248YlQuVHJhbnNhY3Rpb24+PiB7XG4gICAgY29uc3QgeyBoZXgsIGZlZSB9ID0gYXdhaXQgdGhpcy5fYnVpbGRTd2VlcFRyYW5zYWN0aW9uKFxuICAgICAgZXh0ZXJuYWxDaGFuZ2VBZGRyZXNzLFxuICAgICAgZmVlUGVyQnl0ZSxcbiAgICAgIF9vdXRwdXRzLFxuICAgICAgZml4ZWRJbnB1dHMsXG4gICAgKTtcbiAgICBhd2FpdCB0aGlzLmdldE1ldGhvZCgnc2VuZFJhd1RyYW5zYWN0aW9uJykoaGV4KTtcbiAgICByZXR1cm4gbm9ybWFsaXplVHJhbnNhY3Rpb25PYmplY3QoXG4gICAgICBkZWNvZGVSYXdUcmFuc2FjdGlvbihoZXgsIHRoaXMuX25ldHdvcmspLFxuICAgICAgZmVlLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBfYnVpbGRTd2VlcFRyYW5zYWN0aW9uKFxuICAgIGV4dGVybmFsQ2hhbmdlQWRkcmVzczogc3RyaW5nLFxuICAgIGZlZVBlckJ5dGU6IG51bWJlcixcbiAgICBfb3V0cHV0czogT3V0cHV0W10gPSBbXSxcbiAgICBmaXhlZElucHV0czogSW5wdXRbXSxcbiAgKSB7XG4gICAgY29uc3QgX2ZlZVBlckJ5dGUgPVxuICAgICAgZmVlUGVyQnl0ZSB8fFxuICAgICAgKGF3YWl0IHRoaXMuZ2V0TWV0aG9kKCdnZXRGZWVQZXJCeXRlJykoKSkgfHxcbiAgICAgIEZFRV9QRVJfQllURV9GQUxMQkFDSztcbiAgICBjb25zdCBpbnB1dHM6IElucHV0W10gPSBbXTtcbiAgICBjb25zdCBvdXRwdXRzOiBPdXRwdXRbXSA9IFtdO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBpbnB1dHNGb3JBbW91bnQgPSBhd2FpdCB0aGlzLmdldE1ldGhvZCgnZ2V0SW5wdXRzRm9yQW1vdW50JykoXG4gICAgICAgIF9vdXRwdXRzLFxuICAgICAgICBfZmVlUGVyQnl0ZSxcbiAgICAgICAgZml4ZWRJbnB1dHMsXG4gICAgICAgIDEwMCxcbiAgICAgICAgdHJ1ZSxcbiAgICAgICk7XG4gICAgICBpZiAoaW5wdXRzRm9yQW1vdW50LmNoYW5nZSkge1xuICAgICAgICB0aHJvdyBFcnJvcignVGhlcmUgc2hvdWxkIG5vdCBiZSBhbnkgY2hhbmdlIGZvciBzd2VlcGluZyB0cmFuc2FjdGlvbicpO1xuICAgICAgfVxuICAgICAgaW5wdXRzLnB1c2goLi4uKGlucHV0c0ZvckFtb3VudC5pbnB1dHMgfHwgW10pKTtcbiAgICAgIG91dHB1dHMucHVzaCguLi4oaW5wdXRzRm9yQW1vdW50Lm91dHB1dHMgfHwgW10pKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZml4ZWRJbnB1dHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHRocm93IEVycm9yKFxuICAgICAgICAgIGBJbnB1dHMgZm9yIGFtb3VudCBkb2Vzbid0IGV4aXN0IGFuZCBubyBmaXhlZElucHV0cyBwcm92aWRlZGAsXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGlucHV0c0ZvckFtb3VudCA9IGF3YWl0IHRoaXMuX2dldElucHV0Rm9yQW1vdW50V2l0aG91dFV0eG9DaGVjayhcbiAgICAgICAgX291dHB1dHMsXG4gICAgICAgIF9mZWVQZXJCeXRlLFxuICAgICAgICBmaXhlZElucHV0cyxcbiAgICAgICk7XG4gICAgICBpbnB1dHMucHVzaChcbiAgICAgICAgLi4uKGlucHV0c0ZvckFtb3VudC5pbnB1dHMubWFwKCh1dHhvKSA9PiBJbnB1dC5mcm9tVVRYTyh1dHhvKSkgfHwgW10pLFxuICAgICAgKTtcbiAgICAgIG91dHB1dHMucHVzaCguLi4oaW5wdXRzRm9yQW1vdW50Lm91dHB1dHMgfHwgW10pKTtcbiAgICB9XG4gICAgX291dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PiB7XG4gICAgICBjb25zdCBzcGxpY2VJbmRleCA9IG91dHB1dHMuZmluZEluZGV4KFxuICAgICAgICAoc3dlZXBPdXRwdXQ6IE91dHB1dCkgPT4gb3V0cHV0LnZhbHVlID09PSBzd2VlcE91dHB1dC52YWx1ZSxcbiAgICAgICk7XG4gICAgICBvdXRwdXRzLnNwbGljZShzcGxpY2VJbmRleCwgMSk7XG4gICAgfSk7XG4gICAgX291dHB1dHMucHVzaCh7XG4gICAgICB0bzogZXh0ZXJuYWxDaGFuZ2VBZGRyZXNzLFxuICAgICAgdmFsdWU6IG91dHB1dHNbMF0udmFsdWUsXG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMuX2J1aWxkVHJhbnNhY3Rpb25XaXRob3V0VXR4b0NoZWNrKFxuICAgICAgX291dHB1dHMsXG4gICAgICBfZmVlUGVyQnl0ZSxcbiAgICAgIGlucHV0cyxcbiAgICApO1xuICB9XG5cbiAgX2dldElucHV0Rm9yQW1vdW50V2l0aG91dFV0eG9DaGVjayhcbiAgICBfb3V0cHV0czogT3V0cHV0W10sXG4gICAgX2ZlZVBlckJ5dGU6IG51bWJlcixcbiAgICBmaXhlZElucHV0czogSW5wdXRbXSxcbiAgKToge1xuICAgIGlucHV0czogYlQuVVRYT1tdO1xuICAgIG91dHB1dHM6IHsgdmFsdWU6IG51bWJlcjsgaWQ/OiBzdHJpbmcgfVtdO1xuICAgIGZlZTogbnVtYmVyO1xuICAgIGNoYW5nZTogeyB2YWx1ZTogbnVtYmVyOyBpZD86IHN0cmluZyB9O1xuICB9IHtcbiAgICBjb25zdCB1dHhvQmFsYW5jZSA9IGZpeGVkSW5wdXRzLnJlZHVjZSgoYSwgYikgPT4gYSArIChiWyd2YWx1ZSddIHx8IDApLCAwKTtcbiAgICBjb25zdCBvdXRwdXRCYWxhbmNlID0gX291dHB1dHMucmVkdWNlKChhLCBiKSA9PiBhICsgKGJbJ3ZhbHVlJ10gfHwgMCksIDApO1xuICAgIGNvbnN0IGFtb3VudFRvU2VuZCA9XG4gICAgICB1dHhvQmFsYW5jZSAtXG4gICAgICBfZmVlUGVyQnl0ZSAqICgoX291dHB1dHMubGVuZ3RoICsgMSkgKiAzOSArIGZpeGVkSW5wdXRzLmxlbmd0aCAqIDE1Myk7IC8vIHRvZG8gYmV0dGVyIGNhbGN1bGF0aW9uXG5cbiAgICBjb25zdCB0YXJnZXRzID0gX291dHB1dHMubWFwKCh0YXJnZXQsIGkpID0+ICh7XG4gICAgICBpZDogJ21haW4nLFxuICAgICAgdmFsdWU6IHRhcmdldC52YWx1ZSxcbiAgICB9KSk7XG4gICAgaWYgKGFtb3VudFRvU2VuZCAtIG91dHB1dEJhbGFuY2UgPiAwKSB7XG4gICAgICB0YXJnZXRzLnB1c2goeyBpZDogJ21haW4nLCB2YWx1ZTogYW1vdW50VG9TZW5kIC0gb3V0cHV0QmFsYW5jZSB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0Q29pbnMoXG4gICAgICBmaXhlZElucHV0cyxcbiAgICAgIHRhcmdldHMsXG4gICAgICBNYXRoLmNlaWwoX2ZlZVBlckJ5dGUpLFxuICAgICAgZml4ZWRJbnB1dHMsXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIF9idWlsZFRyYW5zYWN0aW9uV2l0aG91dFV0eG9DaGVjayhcbiAgICBvdXRwdXRzOiBPdXRwdXRbXSxcbiAgICBmZWVQZXJCeXRlOiBudW1iZXIsXG4gICAgZml4ZWRJbnB1dHM6IElucHV0W10sXG4gICkge1xuICAgIGNvbnN0IG5ldHdvcmsgPSB0aGlzLl9uZXR3b3JrO1xuXG4gICAgY29uc3QgeyBmZWUgfSA9IHRoaXMuX2dldElucHV0Rm9yQW1vdW50V2l0aG91dFV0eG9DaGVjayhcbiAgICAgIG91dHB1dHMsXG4gICAgICBmZWVQZXJCeXRlLFxuICAgICAgZml4ZWRJbnB1dHMsXG4gICAgKTtcbiAgICBjb25zdCBpbnB1dHMgPSBmaXhlZElucHV0cztcblxuICAgIGNvbnN0IHR4YiA9IG5ldyBiaXRjb2luLlRyYW5zYWN0aW9uQnVpbGRlcihuZXR3b3JrKTtcblxuICAgIGZvciAoY29uc3Qgb3V0cHV0IG9mIG91dHB1dHMpIHtcbiAgICAgIGNvbnN0IHRvID0gb3V0cHV0LnRvOyAvLyBBbGxvdyBmb3IgT1BfUkVUVVJOXG4gICAgICB0eGIuYWRkT3V0cHV0KHRvLCBvdXRwdXQudmFsdWUpO1xuICAgIH1cblxuICAgIGNvbnN0IHByZXZPdXRTY3JpcHRUeXBlID0gJ3Ayd3BraCc7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0cy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgdGhpcy5nZXRNZXRob2QoJ2dldFdhbGxldEFkZHJlc3MnKShcbiAgICAgICAgaW5wdXRzW2ldLmFkZHJlc3MsXG4gICAgICApO1xuICAgICAgY29uc3Qga2V5UGFpciA9IGF3YWl0IHRoaXMuZ2V0TWV0aG9kKCdrZXlQYWlyJykod2FsbGV0LmRlcml2YXRpb25QYXRoKTtcbiAgICAgIGNvbnN0IHBheW1lbnRWYXJpYW50ID0gdGhpcy5nZXRNZXRob2QoJ2dldFBheW1lbnRWYXJpYW50RnJvbVB1YmxpY0tleScpKFxuICAgICAgICBrZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICk7XG5cbiAgICAgIHR4Yi5hZGRJbnB1dChpbnB1dHNbaV0udHhpZCwgaW5wdXRzW2ldLnZvdXQsIDAsIHBheW1lbnRWYXJpYW50Lm91dHB1dCk7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IGF3YWl0IHRoaXMuZ2V0TWV0aG9kKCdnZXRXYWxsZXRBZGRyZXNzJykoXG4gICAgICAgIGlucHV0c1tpXS5hZGRyZXNzLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBhd2FpdCB0aGlzLmdldE1ldGhvZCgna2V5UGFpcicpKHdhbGxldC5kZXJpdmF0aW9uUGF0aCk7XG4gICAgICBjb25zdCBwYXltZW50VmFyaWFudCA9IHRoaXMuZ2V0TWV0aG9kKCdnZXRQYXltZW50VmFyaWFudEZyb21QdWJsaWNLZXknKShcbiAgICAgICAga2V5UGFpci5wdWJsaWNLZXksXG4gICAgICApO1xuICAgICAgY29uc3QgbmVlZHNXaXRuZXNzID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2lnblBhcmFtcyA9IHtcbiAgICAgICAgcHJldk91dFNjcmlwdFR5cGUsXG4gICAgICAgIHZpbjogaSxcbiAgICAgICAga2V5UGFpcixcbiAgICAgICAgd2l0bmVzc1ZhbHVlOiAwLFxuICAgICAgfTtcblxuICAgICAgaWYgKG5lZWRzV2l0bmVzcykge1xuICAgICAgICBzaWduUGFyYW1zLndpdG5lc3NWYWx1ZSA9IGlucHV0c1tpXS52YWx1ZTtcbiAgICAgIH1cblxuICAgICAgdHhiLnNpZ24oc2lnblBhcmFtcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgaGV4OiB0eGIuYnVpbGQoKS50b0hleCgpLCBmZWUgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBxdWlja0dldEFkZHJlc3NlcyBpcyBhbiBvcHRpbWl6ZWQgdmVyc2lvbiBvZiBnZXRBZGRyZXNzZXMuXG4gICAqIEl0IHJlbW92ZXMgdGhlIGNhbGwgdG8gYGFzeW5jU2V0SW1tZWRpYXRlKClgLCBzcGVlZGluZyB1cCB0aGUgZnVuY3Rpb24gYnkgYSBmYWN0b3Igb2YgNnguXG4gICAqXG4gICAqIEBwYXJhbSBzdGFydGluZ0luZGV4XG4gICAqIEBwYXJhbSBudW1BZGRyZXNzZXNcbiAgICogQHBhcmFtIGNoYW5nZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxBZGRyZXNzW10+fVxuICAgKi9cbiAgYXN5bmMgcXVpY2tHZXRBZGRyZXNzZXMoXG4gICAgc3RhcnRpbmdJbmRleCA9IDAsXG4gICAgbnVtQWRkcmVzc2VzID0gMSxcbiAgICBjaGFuZ2UgPSBmYWxzZSxcbiAgKTogUHJvbWlzZTxBZGRyZXNzW10+IHtcbiAgICBpZiAobnVtQWRkcmVzc2VzIDwgMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgbXVzdCByZXR1cm4gYXQgbGVhc3Qgb25lIGFkZHJlc3MnKTtcbiAgICB9XG5cbiAgICBjb25zdCBhZGRyZXNzZXMgPSBbXTtcbiAgICBjb25zdCBsYXN0SW5kZXggPSBzdGFydGluZ0luZGV4ICsgbnVtQWRkcmVzc2VzO1xuICAgIGNvbnN0IGNoYW5nZVZhbCA9IGNoYW5nZSA/ICcxJyA6ICcwJztcblxuICAgIC8vIE9yaWdpbmFsIHdhbGxldCBwcm92aWRlciBpcyBmZXRjaGVkIHRvIGdldCB0aGUgYmFzZSBkZXJpdmF0aW9uIHBhdGhcbiAgICBjb25zdCBvcmlnaW5hbFByb3ZpZGVyID0gdGhpcy5jbGllbnQuZ2V0UHJvdmlkZXJGb3JNZXRob2QoJ2dldEFkZHJlc3NlcycpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgY29uc3QgYmFzZURlcml2YXRpb25QYXRoID0gKG9yaWdpbmFsUHJvdmlkZXIgYXMgYW55KVxuICAgICAgLl9iYXNlRGVyaXZhdGlvblBhdGggYXMgc3RyaW5nO1xuXG4gICAgY29uc3QgZ2V0RGVyaXZhdGlvblBhdGhBZGRyZXNzRm46IChcbiAgICAgIHBhdGg6IHN0cmluZyxcbiAgICApID0+IFByb21pc2U8QWRkcmVzcz4gPSB0aGlzLmNsaWVudC5nZXRNZXRob2QoJ2dldERlcml2YXRpb25QYXRoQWRkcmVzcycpO1xuXG4gICAgZm9yIChcbiAgICAgIGxldCBjdXJyZW50SW5kZXggPSBzdGFydGluZ0luZGV4O1xuICAgICAgY3VycmVudEluZGV4IDwgbGFzdEluZGV4O1xuICAgICAgY3VycmVudEluZGV4KytcbiAgICApIHtcbiAgICAgIGNvbnN0IHN1YlBhdGggPSBjaGFuZ2VWYWwgKyAnLycgKyBjdXJyZW50SW5kZXg7XG4gICAgICBjb25zdCBwYXRoID0gYmFzZURlcml2YXRpb25QYXRoICsgJy8nICsgc3ViUGF0aDtcbiAgICAgIGNvbnN0IGFkZHJlc3NPYmplY3QgPSBhd2FpdCBnZXREZXJpdmF0aW9uUGF0aEFkZHJlc3NGbihwYXRoKTtcbiAgICAgIGFkZHJlc3Nlcy5wdXNoKGFkZHJlc3NPYmplY3QpO1xuICAgIH1cblxuICAgIHJldHVybiBhZGRyZXNzZXM7XG4gIH1cblxuICAvKipcbiAgICogcXVpY2tGaW5kQWRkcmVzcyBpcyBhbiBvcHRpbWl6ZWQgdmVyc2lvbiBvZiBmaW5kQWRkcmVzcy5cbiAgICpcbiAgICogSXQgc2VhcmNoZXMgdGhyb3VnaCBib3RoIGNoYW5nZSBhbmQgbm9uLWNoYW5nZSBhZGRyZXNzZXMgZWFjaCBpdGVyYXRpb24uXG4gICAqXG4gICAqIFRoaXMgaXMgaW4gY29udHJhc3QgdG8gdGhlIG9yaWdpbmFsIGZpbmRBZGRyZXNzIGZ1bmN0aW9uIHdoaWNoIHNlYXJjaGVzXG4gICAqIHRocm91Z2ggYWxsIG5vbi1jaGFuZ2UgYWRkcmVzc2VzIGJlZm9yZSBtb3Zpbmcgb24gdG8gY2hhbmdlIGFkZHJlc3Nlcy5cbiAgICpcbiAgICogQHBhcmFtIGFkZHJlc3Nlc1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxBZGRyZXNzW10+fVxuICAgKi9cbiAgYXN5bmMgcXVpY2tGaW5kQWRkcmVzcyhhZGRyZXNzZXM6IHN0cmluZ1tdKTogUHJvbWlzZTxBZGRyZXNzPiB7XG4gICAgY29uc3QgYWRkcmVzc2VzUGVyQ2FsbCA9IDIwO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICB3aGlsZSAoaW5kZXggPCB0aGlzLl9tYXhBZGRyZXNzZXNUb0Rlcml2ZSkge1xuICAgICAgY29uc3Qgd2FsbGV0Tm9uQ2hhbmdlQWRkcmVzc2VzID0gYXdhaXQgdGhpcy5xdWlja0dldEFkZHJlc3NlcyhcbiAgICAgICAgaW5kZXgsXG4gICAgICAgIGFkZHJlc3Nlc1BlckNhbGwsXG4gICAgICAgIHRydWUsXG4gICAgICApO1xuICAgICAgY29uc3Qgd2FsbGV0Q2hhbmdlQWRkcmVzc2VzID0gYXdhaXQgdGhpcy5xdWlja0dldEFkZHJlc3NlcyhcbiAgICAgICAgaW5kZXgsXG4gICAgICAgIGFkZHJlc3Nlc1BlckNhbGwsXG4gICAgICAgIGZhbHNlLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHdhbGxldEFkZHJlc3NlcyA9IFtcbiAgICAgICAgLi4ud2FsbGV0Tm9uQ2hhbmdlQWRkcmVzc2VzLFxuICAgICAgICAuLi53YWxsZXRDaGFuZ2VBZGRyZXNzZXMsXG4gICAgICBdO1xuICAgICAgY29uc3Qgd2FsbGV0QWRkcmVzcyA9IHdhbGxldEFkZHJlc3Nlcy5maW5kKCh3YWxsZXRBZGRyKSA9PlxuICAgICAgICBhZGRyZXNzZXMuZmluZCgoYWRkcikgPT4gd2FsbGV0QWRkci5hZGRyZXNzID09PSBhZGRyKSxcbiAgICAgICk7XG5cbiAgICAgIGlmICh3YWxsZXRBZGRyZXNzKSB7XG4gICAgICAgIC8vIEluY3JlbWVudCBtYXggYWRkcmVzc2VzIHRvIGRlcml2ZSBieSAxMDAgaWYgZm91bmQgd2l0aGluIDEwMCBhZGRyZXNzZXMgb2YgbWF4QWRkcmVzc2VzVG9EZXJpdmVcbiAgICAgICAgdGhpcy5fbWF4QWRkcmVzc2VzVG9EZXJpdmUgPSBNYXRoLm1heChcbiAgICAgICAgICB0aGlzLl9tYXhBZGRyZXNzZXNUb0Rlcml2ZSxcbiAgICAgICAgICBpbmRleCArIDEwMCxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHdhbGxldEFkZHJlc3M7XG4gICAgICB9XG4gICAgICBpbmRleCArPSBhZGRyZXNzZXNQZXJDYWxsO1xuICAgIH1cbiAgfVxufVxuIl0sIm5hbWVzIjpbImJpdGNvaW4iLCJGRUVfUEVSX0JZVEVfRkFMTEJBQ0siLCJBRERSRVNTX0dBUCIsIk5PTkNIQU5HRV9BRERSRVNTIiwiQ0hBTkdFX0FERFJFU1MiLCJOT05DSEFOR0VfT1JfQ0hBTkdFX0FERFJFU1MiLCJCaXRjb2luV2FsbGV0UHJvdmlkZXIiLCJQcm92aWRlciIsImJ1aWxkU3dlZXBUcmFuc2FjdGlvbldpdGhTZXRPdXRwdXRzIiwiZXh0ZXJuYWxDaGFuZ2VBZGRyZXNzIiwiZmVlUGVyQnl0ZSIsIl9vdXRwdXRzIiwiZml4ZWRJbnB1dHMiLCJfYnVpbGRTd2VlcFRyYW5zYWN0aW9uIiwiZ2V0VW51c2VkQWRkcmVzc2VzQmxhY2tsaXN0IiwiX3VudXNlZEFkZHJlc3Nlc0JsYWNrbGlzdCIsInNldFVudXNlZEFkZHJlc3Nlc0JsYWNrbGlzdCIsInVudXNlZEFkZHJlc3Nlc0JsYWNrbGlzdCIsInNldE1heEFkZHJlc3Nlc1RvRGVyaXZlIiwibWF4QWRkcmVzc2VzVG9EZXJpdmUiLCJfbWF4QWRkcmVzc2VzVG9EZXJpdmUiLCJnZXRNYXhBZGRyZXNzZXNUb0Rlcml2ZSIsIl9jcmVhdGVNdWx0aXNpZ1BheW1lbnQiLCJtIiwicHVia2V5cyIsImxlbmd0aCIsIkVycm9yIiwicDJtcyIsInBheW1lbnRzIiwibWFwIiwia2V5IiwiQnVmZmVyIiwiZnJvbSIsIm5ldHdvcmsiLCJfbmV0d29yayIsInAyd3NoIiwicmVkZWVtIiwiY3JlYXRlTXVsdGlzaWciLCJhZGRyZXNzIiwicmVkZWVtU2NyaXB0Iiwib3V0cHV0IiwidG9TdHJpbmciLCJidWlsZE11bHRpc2lnUFNCVCIsImlucHV0cyIsIm91dHB1dHMiLCJhc3NlcnQiLCJldmVyeSIsImlucHV0Iiwic2NyaXB0UHViS2V5IiwicHNidCIsIlBzYnQiLCJmb3JFYWNoIiwiYWRkSW5wdXQiLCJoYXNoIiwidHhpZCIsImluZGV4Iiwidm91dCIsIndpdG5lc3NVdHhvIiwic2NyaXB0IiwidmFsdWUiLCJ3aXRuZXNzU2NyaXB0IiwiYWRkT3V0cHV0IiwidG8iLCJ0b0Jhc2U2NCIsIndhbGxldFByb2Nlc3NQU0JUIiwicHNidFN0cmluZyIsImZyb21CYXNlNjQiLCJQcm9taXNlIiwiYWxsIiwiZGF0YSIsImkiLCJnZXRJbnB1dFR5cGUiLCJzbGljZSIsInNjcmlwdFN0YWNrIiwiZGVjb21waWxlIiwiZmlsdGVyIiwiaXNCdWZmZXIiLCJzZWNwMjU2azEiLCJwdWJsaWNLZXlWZXJpZnkiLCJhZGRyZXNzU3RyaW5nIiwicDJ3cGtoIiwicHVia2V5IiwicXVpY2tGaW5kQWRkcmVzcyIsImtleVBhaXIiLCJnZXRNZXRob2QiLCJkZXJpdmF0aW9uUGF0aCIsInNpZ25JbnB1dCIsInZhbGlkYXRlU2lnbmF0dXJlc09mQWxsSW5wdXRzIiwiZmluYWxpemVQU0JUIiwiZmluYWxpemVBbGxJbnB1dHMiLCJlcnJvciIsImNvbXBsZXRlIiwiaGV4IiwiZXh0cmFjdFRyYW5zYWN0aW9uIiwidG9IZXgiLCJnZXRVbnVzZWRBZGRyZXNzIiwiY2hhbmdlIiwibnVtQWRkcmVzc1BlckNhbGwiLCJhZGRyZXNzVHlwZSIsIl9nZXRVc2VkVW51c2VkQWRkcmVzc2VzIiwidGhlbiIsInVudXNlZEFkZHJlc3MiLCJ1c2VkQWRkcmVzc2VzIiwiYWRkcmVzc0NvdW50TWFwIiwibm9uQ2hhbmdlIiwidW51c2VkQWRkcmVzc01hcCIsImFkZHJMaXN0IiwiYWRkcmVzc0luZGV4IiwiY2hhbmdlQWRkcmVzc2VzIiwibm9uQ2hhbmdlQWRkcmVzc2VzIiwiY2xpZW50Iiwid2FsbGV0IiwiZ2V0QWRkcmVzc2VzIiwiY29uY2F0IiwicXVpY2tHZXRBZGRyZXNzZXMiLCJ0cmFuc2FjdGlvbkNvdW50cyIsImlzVXNlZCIsImlzQ2hhbmdlQWRkcmVzcyIsImZpbmQiLCJhIiwicHVzaCIsImZpcnN0VW51c2VkQWRkcmVzcyIsImluZGV4Tm9uQ2hhbmdlIiwiSW5maW5pdHkiLCJpbmRleENoYW5nZSIsInNlbmRTd2VlcFRyYW5zYWN0aW9uV2l0aFNldE91dHB1dHMiLCJmZWUiLCJub3JtYWxpemVUcmFuc2FjdGlvbk9iamVjdCIsImRlY29kZVJhd1RyYW5zYWN0aW9uIiwiX2ZlZVBlckJ5dGUiLCJpbnB1dHNGb3JBbW91bnQiLCJlIiwiX2dldElucHV0Rm9yQW1vdW50V2l0aG91dFV0eG9DaGVjayIsInV0eG8iLCJJbnB1dCIsImZyb21VVFhPIiwic3BsaWNlSW5kZXgiLCJmaW5kSW5kZXgiLCJzd2VlcE91dHB1dCIsInNwbGljZSIsIl9idWlsZFRyYW5zYWN0aW9uV2l0aG91dFV0eG9DaGVjayIsInV0eG9CYWxhbmNlIiwicmVkdWNlIiwiYiIsIm91dHB1dEJhbGFuY2UiLCJhbW91bnRUb1NlbmQiLCJ0YXJnZXRzIiwidGFyZ2V0IiwiaWQiLCJzZWxlY3RDb2lucyIsIk1hdGgiLCJjZWlsIiwidHhiIiwiVHJhbnNhY3Rpb25CdWlsZGVyIiwicHJldk91dFNjcmlwdFR5cGUiLCJwYXltZW50VmFyaWFudCIsInB1YmxpY0tleSIsIm5lZWRzV2l0bmVzcyIsInNpZ25QYXJhbXMiLCJ2aW4iLCJ3aXRuZXNzVmFsdWUiLCJzaWduIiwiYnVpbGQiLCJzdGFydGluZ0luZGV4IiwibnVtQWRkcmVzc2VzIiwiYWRkcmVzc2VzIiwibGFzdEluZGV4IiwiY2hhbmdlVmFsIiwib3JpZ2luYWxQcm92aWRlciIsImdldFByb3ZpZGVyRm9yTWV0aG9kIiwiYmFzZURlcml2YXRpb25QYXRoIiwiX2Jhc2VEZXJpdmF0aW9uUGF0aCIsImdldERlcml2YXRpb25QYXRoQWRkcmVzc0ZuIiwiY3VycmVudEluZGV4Iiwic3ViUGF0aCIsInBhdGgiLCJhZGRyZXNzT2JqZWN0IiwiYWRkcmVzc2VzUGVyQ2FsbCIsIndhbGxldE5vbkNoYW5nZUFkZHJlc3NlcyIsIndhbGxldENoYW5nZUFkZHJlc3NlcyIsIndhbGxldEFkZHJlc3NlcyIsIndhbGxldEFkZHJlc3MiLCJ3YWxs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
|
|
409
|
+
//# sourceMappingURL=BitcoinWalletProvider.js.map
|