PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-stx/dist/test/unit
Просмотр файла: stx.js
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const assert_1 = __importDefault(require("assert"));
const nock_1 = __importDefault(require("nock"));
const sdk_api_1 = require("@bitgo/sdk-api");
const sdk_core_1 = require("@bitgo/sdk-core");
const sdk_test_1 = require("@bitgo/sdk-test");
const statics_1 = require("@bitgo/statics");
const transactions_1 = require("@stacks/transactions");
const testData = __importStar(require("../fixtures"));
const src_1 = require("../../src");
const { KeyPair } = src_1.StxLib;
describe('STX:', function () {
const coinName = 'stx';
const coinNameTest = 'tstx';
let bitgo;
let basecoin;
const badValidAddresses = [
'',
null,
'abc',
'SP244HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6',
'ST1T758K6T2YRKG9Q0TJ16B6FP5QQREWZSESRS0PY',
];
const goodAddresses = [
'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6',
'ST11NJTTKGVT6D1HY4NJRVQWMQM7TVAR091EJ8P2Y',
'SP2T758K6T2YRKG9Q0TJ16B6FP5QQREWZSESRS0PY',
'SM3W5QFWGPG1JC8R25EVZDEP3BESJZ831JPNNQFTZ',
'SM3W5QFWGPG1JC8R25EVZDEP3BESJZ831JPNNQFTZ?memoId=1',
'ST1WVJMS5VS41F0YMH7D2M0VHXRG4CY43ZJZBS60A?memoId=4',
];
before(function () {
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, {
env: 'mock',
});
bitgo.initializeTestVars();
bitgo.safeRegister('stx', src_1.Stx.createInstance);
bitgo.safeRegister('tstx', src_1.Tstx.createInstance);
basecoin = bitgo.coin(coinNameTest);
});
/**
* Build an unsigned account-lib signle-signature send transaction
* @param destination The destination address of the transaction
* @param amount The amount to send to the recipient
*/
const buildUnsignedTransaction = async function ({ destination, amount = '100000', publicKey, memo = '' }) {
const factory = new src_1.StxLib.TransactionBuilderFactory(statics_1.coins.get(coinName));
const txBuilder = factory.getTransferBuilder();
txBuilder.fee({
fee: '180',
});
txBuilder.to(destination);
txBuilder.amount(amount);
txBuilder.nonce(1);
txBuilder.fromPubKey(publicKey);
txBuilder.memo(memo);
txBuilder.numberSignatures(1);
return await txBuilder.build();
};
/**
* Build an unsigned account-lib multi-signature send transaction
* @param destination The destination address of the transaction
* @param amount The amount to send to the recipient
*/
const buildmultiSigUnsignedTransaction = async function ({ destination, amount = '100000', publicKeys, memo = '' }) {
const factory = new src_1.StxLib.TransactionBuilderFactory(statics_1.coins.get(coinName));
const txBuilder = factory.getTransferBuilder();
txBuilder.fee({
fee: '180',
});
txBuilder.to(destination);
txBuilder.amount(amount);
txBuilder.nonce(1);
txBuilder.fromPubKey(publicKeys);
txBuilder.numberSignatures(2);
txBuilder.memo(memo);
return await txBuilder.build();
};
it('should instantiate the coin', function () {
let localBasecoin = bitgo.coin('tstx');
localBasecoin.should.be.an.instanceof(src_1.Tstx);
localBasecoin = bitgo.coin('stx');
localBasecoin.should.be.an.instanceof(src_1.Stx);
});
it('should check valid addresses', function () {
badValidAddresses.map((addr) => {
basecoin.isValidAddress(addr).should.equal(false);
});
goodAddresses.map((addr) => {
basecoin.isValidAddress(addr).should.equal(true);
});
});
it('should verify isWalletAddress', async function () {
const userKey = {
pub: 'xpub661MyMwAqRbcGS2HMdvANN7o8ESWqwvr5U4ry5fZdD9VHhymWyfoDQF4vzfKotXgGtJTrwrFRz7XbGFov4FqdKKo6mRYNWvMp7P23DjuJnS',
};
const backupKey = {
pub: 'xpub661MyMwAqRbcFEzr5CcpFzPG45rmPf75DTvDobN5gJimCatbHtzR53SbHzDZ1J56byKSsdc8vSujGuQpyPjb7Lsua2NfADJewPxNzL3N6Tj',
};
const bitgoKey = {
pub: 'xpub661MyMwAqRbcGP1adk34VzRQJEMX25rCxjEyU9YFFWNhWNzwPoqgjLoKfnqotLwrz7kBevWbRZnqTSQrQDuJuYUQaDQ5DDPEzEXMwPS9PEf',
};
const keychains = [userKey, backupKey, bitgoKey];
const validAddress1 = 'SNAYQFZ6EF54D5XWJP3GAE1Y8DPYXKFC7TTMYXFV';
const validAddress2 = 'SNAYQFZ6EF54D5XWJP3GAE1Y8DPYXKFC7TTMYXFV?memoId=2';
const unrelatedValidAddress = 'ST11NJTTKGVT6D1HY4NJRVQWMQM7TVAR091EJ8P2Y?memoId=1';
const invalidAddress = 'ST1T758K6T2YRKG9Q0TJ16B6FP5QQREWZSESRS0PY';
(await basecoin.isWalletAddress({ address: validAddress1, keychains })).should.true();
(await basecoin.isWalletAddress({ address: validAddress2, keychains })).should.true();
(await basecoin.isWalletAddress({ address: unrelatedValidAddress, keychains })).should.false();
assert_1.default.rejects(async () => basecoin.isWalletAddress({ address: invalidAddress, keychains }), `invalid address ${invalidAddress}`);
});
it('should explain a transfer transaction', async function () {
const explain = await basecoin.explainTransaction({
txHex: testData.txForExplainTransfer,
feeInfo: { fee: '' },
});
explain.id.should.equal(testData.txExplainedTransfer.id);
explain.outputAmount.should.equal(testData.txExplainedTransfer.outputAmount);
explain.outputs[0].amount.should.equal(testData.txExplainedTransfer.outputAmount);
explain.outputs[0].address.should.equal(testData.txExplainedTransfer.recipient);
explain.outputs[0].memo.should.equal(testData.txExplainedTransfer.memo);
explain.fee.should.equal(testData.txExplainedTransfer.fee);
explain.changeAmount.should.equal('0');
});
it('should explain an unsigned transaction', async function () {
const key = new KeyPair();
const destination = 'ST11NJTTKGVT6D1HY4NJRVQWMQM7TVAR091EJ8P2Y';
const amount = '100000';
const memo = 'i cannot be broadcast';
const unsignedTransaction = await buildUnsignedTransaction({
destination,
amount,
publicKey: key.getKeys().pub,
memo: memo,
});
const unsignedHex = unsignedTransaction.toBroadcastFormat();
const explain = await basecoin.explainTransaction({
txHex: unsignedHex,
publicKeys: [key.getKeys().pub],
feeInfo: { fee: '' },
});
explain.memo.should.equal(memo);
explain.outputs[0].amount.should.equal(amount);
explain.outputs[0].address.should.equal(destination);
});
it('should explain unsigned transfer transaction hex', async function () {
const explain = await basecoin.explainTransaction({
txHex: testData.unsignedTxForExplainTransfer,
publicKeys: ['03797dd653040d344fd048c1ad05d4cbcb2178b30c6a0c4276994795f3e833da41'],
feeInfo: { fee: '' },
});
explain.outputAmount.should.equal(testData.unsignedTxExplainedTransfer.outputAmount);
explain.outputs[0].amount.should.equal(testData.unsignedTxExplainedTransfer.outputAmount);
explain.outputs[0].address.should.equal(testData.unsignedTxExplainedTransfer.recipient);
explain.outputs[0].memo.should.equal(testData.unsignedTxExplainedTransfer.memo);
explain.fee.should.equal(testData.unsignedTxExplainedTransfer.fee);
explain.changeAmount.should.equal('0');
});
it('should explain a contract call transaction', async function () {
const explain = await basecoin.explainTransaction({
txHex: testData.txForExplainContract,
feeInfo: { fee: '' },
});
explain.id.should.equal(testData.txExplainedContract.id);
explain.fee.should.equal(testData.txExplainedContract.fee);
explain.contractAddress.should.equal(testData.txExplainedContract.contractAddress);
explain.contractName.should.equal(testData.txExplainedContract.contractName);
explain.contractFunction.should.equal(testData.txExplainedContract.functionName);
explain.contractFunctionArgs[0].type.should.equal(testData.txExplainedContract.functionArgs[0].type);
explain.contractFunctionArgs[0].value.toString().should.equal(testData.txExplainedContract.functionArgs[0].value);
});
it('should explain a fungible token transfer transaction with memo', async function () {
const explain = await basecoin.explainTransaction({
txHex: testData.txForExplainFungibleTokenTransfer,
feeInfo: { fee: '' },
});
explain.id.should.equal(testData.fungibleTokenTransferTx.id);
explain.fee.should.equal(testData.fungibleTokenTransferTx.fee);
explain.memo.should.equal('1');
explain.outputAmount.should.equal(testData.fungibleTokenTransferTx.functionArgs[2].value);
explain.outputs[0].amount.should.equal(testData.fungibleTokenTransferTx.functionArgs[2].value);
explain.outputs[0].address.should.equal((0, transactions_1.cvToString)(testData.fungibleTokenTransferTx.functionArgs[1]));
explain.outputs[0].memo.should.equal('1');
explain.outputs[0].tokenName.should.equal(testData.fungibleTokenTransferTx.tokenName);
});
it('should explain a fungible token transfer transaction without memo', async function () {
const explain = await basecoin.explainTransaction({
txHex: testData.txForExplainFungibleTokenTransferWithoutMemo,
feeInfo: { fee: '' },
});
explain.id.should.equal(testData.hexWithoutMemoTransferId);
explain.fee.should.equal(testData.fungibleTokenTransferTx.fee);
assert_1.default.deepEqual(explain.memo, undefined, 'memo should be undefined');
explain.outputAmount.should.equal(testData.fungibleTokenTransferTx.functionArgs[2].value);
explain.outputs[0].amount.should.equal(testData.fungibleTokenTransferTx.functionArgs[2].value);
explain.outputs[0].address.should.equal((0, transactions_1.cvToString)(testData.fungibleTokenTransferTx.functionArgs[1]));
assert_1.default.deepEqual(explain.outputs[0].memo, undefined, 'memo should be undefined');
explain.outputs[0].tokenName.should.equal(testData.fungibleTokenTransferTx.tokenName);
});
describe('Keypairs:', () => {
it('should generate a keypair from random seed', function () {
const keyPair = basecoin.generateKeyPair();
keyPair.should.have.property('pub');
keyPair.should.have.property('prv');
});
it('should generate a keypair from a seed', function () {
const seedText = '80350b4208d381fbfe2276a326603049fe500731c46d3c9936b5ce036b51377f24bab7dd0c2af7f107416ef858ff79b0670c72406dad064e72bb17fc0a9038bb';
const seed = Buffer.from(seedText, 'hex');
const keyPair = basecoin.generateKeyPair(seed);
keyPair.pub.should.equal('xpub661MyMwAqRbcFAwqvSGbk35kJf7CQqdN1w4CMUBBTqH5e3ivjU6D8ugv9hRSgRbRenC4w3ahXdLVahwjgjXhSuQKMdNdn55Y9TNSagBktws');
keyPair.prv.should.equal('xprv9s21ZrQH143K2gsNpQjbNu91kdGi1NuWei8bZ5mZuVk6mFPnBvmxb7NSJQdbZW3FGpK3Ycn7jorAXcEzMvviGtbyBz5tBrjfnWyQp3g75FK');
});
});
describe('Sign transaction:', () => {
it('should sign transaction', async function () {
const key = new KeyPair({
prv: '21d43d2ae0da1d9d04cfcaac7d397a33733881081f0b2cd038062cf0ccbb752601',
});
const destination = 'STDE7Y8HV3RX8VBM2TZVWJTS7ZA1XB0SSC3NEVH0';
const amount = '100000';
const unsignedTransaction = await buildUnsignedTransaction({
destination,
amount,
publicKey: key.getKeys().pub,
});
const tx = await basecoin.signTransaction({
prv: key.getKeys().prv.toString(),
pubKeys: [key.getKeys().pub],
txPrebuild: {
txHex: unsignedTransaction.toBroadcastFormat(),
},
});
const factory = new src_1.StxLib.TransactionBuilderFactory(statics_1.coins.get(coinName));
const txBuilder = factory.from(tx.halfSigned.txHex);
const signedTx = await txBuilder.build();
const txJson = signedTx.toJson();
txJson.payload.to.should.equal(destination);
txJson.payload.amount.should.equal(amount);
signedTx.signature.length.should.equal(1);
});
it('should sign multisig transaction', async function () {
const key1 = new KeyPair({
prv: '21d43d2ae0da1d9d04cfcaac7d397a33733881081f0b2cd038062cf0ccbb752601',
});
const key2 = new KeyPair({
prv: 'c71700b07d520a8c9731e4d0f095aa6efb91e16e25fb27ce2b72e7b698f8127a01',
});
const key3 = new KeyPair({
prv: 'e75dcb66f84287eaf347955e94fa04337298dbd95aa0dbb985771104ef1913db01',
});
const destination = 'STDE7Y8HV3RX8VBM2TZVWJTS7ZA1XB0SSC3NEVH0';
const amount = '100000';
const publicKeys = [key1.getKeys(true).pub, key2.getKeys(true).pub, key3.getKeys(true).pub];
const unsignedTransaction = await buildmultiSigUnsignedTransaction({
destination,
amount,
publicKeys,
});
const tx = await basecoin.signTransaction({
prv: [
'21d43d2ae0da1d9d04cfcaac7d397a33733881081f0b2cd038062cf0ccbb752601',
'c71700b07d520a8c9731e4d0f095aa6efb91e16e25fb27ce2b72e7b698f8127a01',
],
pubKeys: [key1.getKeys().pub, key2.getKeys().pub, key3.getKeys().pub],
numberSignature: 2,
txPrebuild: {
txHex: unsignedTransaction.toBroadcastFormat(),
},
});
const factory = new src_1.StxLib.TransactionBuilderFactory(statics_1.coins.get(coinName));
const txBuilder = factory.from(tx.txHex);
const signedTx = await txBuilder.build();
const txJson = signedTx.toJson();
txJson.payload.to.should.equal(destination);
txJson.payload.amount.should.equal(amount);
});
});
describe('getSigningPayload', function () {
it('should return the tx as a buffer', async function () {
const nonTSSCoin = bitgo.coin('tstx');
const bufferTx = await nonTSSCoin.getSignablePayload(testData.unsignedTxForExplainTransfer);
bufferTx.should.be.deepEqual(Buffer.from(testData.unsignedTxForExplainTransfer));
});
});
describe('Verify Transaction', function () {
const address1 = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
const address2 = '0x7e85bdc27c050e3905ebf4b8e634d9ad6edd0de6';
it('should reject a txPrebuild with more than one recipient', async function () {
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
const txParams = {
recipients: [
{ amount: '1000000000000', address: address1 },
{ amount: '2500000000000', address: address2 },
],
wallet: wallet,
walletPassphrase: 'fakeWalletPassphrase',
};
await basecoin
.verifyTransaction({ txParams })
.should.be.rejectedWith(`tstx doesn't support sending to more than 1 destination address within a single transaction. Try again, using only a single recipient.`);
});
});
describe('Recover Transaction STX', function () {
before(function () {
nock_1.default.enableNetConnect();
});
beforeEach(function () {
nock_1.default.cleanAll();
});
after(function () {
nock_1.default.disableNetConnect();
});
it('should build a signed recover transaction when private key data is passed', async function () {
const rootAddress = testData.HOT_WALLET_ROOT_ADDRESS;
(0, nock_1.default)(`https://api.testnet.hiro.so`)
.get(`/extended/v2/addresses/${rootAddress}/balances/stx`)
.reply(200, testData.ACCOUNT_BALANCE_RESPONSE);
(0, nock_1.default)(`https://api.testnet.hiro.so`)
.get(`/extended/v1/address/${rootAddress}/nonces`)
.reply(200, testData.ACCOUNT_NONCE_RESPONSE);
(0, nock_1.default)(`https://api.testnet.hiro.so`, { allowUnmocked: true })
.post(`/v2/fees/transaction`, testData.FEE_ESTIMATION_REQUEST)
.reply(200, testData.FEE_ESTIMATION_RESPONSE);
const recoveryOptions = {
backupKey: testData.HOT_WALLET_KEY_CARD_INFO.BACKUP_KEY,
userKey: testData.HOT_WALLET_KEY_CARD_INFO.USER_KEY,
rootAddress: rootAddress,
recoveryDestination: testData.DESTINATION_ADDRESS_WRW,
bitgoKey: testData.HOT_WALLET_KEY_CARD_INFO.BITGO_PUB_KEY,
walletPassphrase: testData.HOT_WALLET_KEY_CARD_INFO.WALLET_PASSPHRASE,
};
const response = await basecoin.recover(recoveryOptions);
response.should.have.property('txHex');
assert_1.default.deepEqual(response.txHex, testData.HOT_WALLET_RECOVERY_TX_HEX, 'tx hex not matching!');
});
it('should build an unsigned transaction when public keys are passed', async function () {
const rootAddress = testData.COLD_WALLET_ROOT_ADDRESS;
(0, nock_1.default)(`https://api.testnet.hiro.so`)
.get(`/extended/v2/addresses/${rootAddress}/balances/stx`)
.reply(200, testData.ACCOUNT_BALANCE_RESPONSE);
(0, nock_1.default)(`https://api.testnet.hiro.so`)
.get(`/extended/v1/address/${rootAddress}/nonces`)
.reply(200, testData.ACCOUNT_NONCE_RESPONSE);
(0, nock_1.default)(`https://api.testnet.hiro.so`, { allowUnmocked: true })
.post(`/v2/fees/transaction`, testData.FEE_ESTIMATION_REQUEST)
.reply(200, testData.FEE_ESTIMATION_RESPONSE);
const recoveryOptions = {
backupKey: testData.COLD_WALLET_PUBLIC_KEY_INFO.BACKUP_KEY,
userKey: testData.COLD_WALLET_PUBLIC_KEY_INFO.USER_KEY,
rootAddress: rootAddress,
recoveryDestination: testData.DESTINATION_ADDRESS_WRW,
bitgoKey: testData.COLD_WALLET_PUBLIC_KEY_INFO.BITGO_PUB_KEY,
};
const response = await basecoin.recover(recoveryOptions);
response.should.have.property('txHex');
response.should.have.property('coin');
response.should.have.property('feeInfo');
assert_1.default.deepEqual(response.txHex, testData.COLD_WALLET_UNSIGNED_SWEEP_TX_HEX, 'tx hex not matching!');
assert_1.default.deepEqual(response.coin, 'tstx', 'coin not matching!');
});
it('should throw invalid root address when root address is missing or invalid', async function () {
const recoveryOptions = {
backupKey: testData.COLD_WALLET_PUBLIC_KEY_INFO.BACKUP_KEY,
userKey: testData.COLD_WALLET_PUBLIC_KEY_INFO.USER_KEY,
rootAddress: '',
recoveryDestination: testData.DESTINATION_ADDRESS_WRW,
bitgoKey: testData.COLD_WALLET_PUBLIC_KEY_INFO.BITGO_PUB_KEY,
};
await basecoin.recover(recoveryOptions).should.rejectedWith('invalid root address!');
});
it('should throw invalid destination address when destination address is missing or invalid', async function () {
const recoveryOptions = {
backupKey: testData.COLD_WALLET_PUBLIC_KEY_INFO.BACKUP_KEY,
userKey: testData.COLD_WALLET_PUBLIC_KEY_INFO.USER_KEY,
rootAddress: testData.COLD_WALLET_ROOT_ADDRESS,
recoveryDestination: '',
bitgoKey: testData.COLD_WALLET_PUBLIC_KEY_INFO.BITGO_PUB_KEY,
};
await basecoin.recover(recoveryOptions).should.rejectedWith('invalid destination address!');
});
it("should fail with no balance when root address doesn't have balance", async function () {
const rootAddress = testData.HOT_WALLET_ROOT_ADDRESS;
const stxBalance = JSON.parse(JSON.stringify(testData.ACCOUNT_BALANCE_RESPONSE));
stxBalance.balance = '0';
(0, nock_1.default)(`https://api.testnet.hiro.so`)
.get(`/extended/v2/addresses/${rootAddress}/balances/stx`)
.reply(200, stxBalance);
(0, nock_1.default)(`https://api.testnet.hiro.so`)
.get(`/extended/v1/address/${rootAddress}/nonces`)
.reply(200, testData.ACCOUNT_NONCE_RESPONSE);
const recoveryOptions = {
backupKey: testData.HOT_WALLET_KEY_CARD_INFO.BACKUP_KEY,
userKey: testData.HOT_WALLET_KEY_CARD_INFO.USER_KEY,
rootAddress: rootAddress,
recoveryDestination: testData.DESTINATION_ADDRESS_WRW,
bitgoKey: testData.HOT_WALLET_KEY_CARD_INFO.BITGO_PUB_KEY,
walletPassphrase: testData.HOT_WALLET_KEY_CARD_INFO.WALLET_PASSPHRASE,
};
await basecoin
.recover(recoveryOptions)
.should.rejectedWith(`could not find any balance to recover for ${rootAddress}`);
});
it('should fail with insufficient balance when stx balance is lower than fee', async function () {
const rootAddress = testData.HOT_WALLET_ROOT_ADDRESS;
// deep clone to stop mutation
const accountBalance = JSON.parse(JSON.stringify(testData.ACCOUNT_BALANCE_RESPONSE));
accountBalance.balance = '100'; // set balance lower than fee
(0, nock_1.default)(`https://api.testnet.hiro.so`)
.get(`/extended/v2/addresses/${rootAddress}/balances/stx`)
.reply(200, accountBalance);
(0, nock_1.default)(`https://api.testnet.hiro.so`)
.get(`/extended/v1/address/${rootAddress}/nonces`)
.reply(200, testData.ACCOUNT_NONCE_RESPONSE);
const feeRequestBody = testData.FEE_ESTIMATION_REQUEST;
feeRequestBody.transaction_payload =
'00051a1500a1c42f0c11bfe3893f479af18904677685be000000000000006400000000000000000000000000000000000000000000000000000000000000000000';
(0, nock_1.default)(`https://api.testnet.hiro.so`, { allowUnmocked: true })
.post(`/v2/fees/transaction`, feeRequestBody)
.reply(200, testData.FEE_ESTIMATION_RESPONSE);
const recoveryOptions = {
backupKey: testData.HOT_WALLET_KEY_CARD_INFO.BACKUP_KEY,
userKey: testData.HOT_WALLET_KEY_CARD_INFO.USER_KEY,
rootAddress: rootAddress,
recoveryDestination: testData.DESTINATION_ADDRESS_WRW,
bitgoKey: testData.HOT_WALLET_KEY_CARD_INFO.BITGO_PUB_KEY,
walletPassphrase: testData.HOT_WALLET_KEY_CARD_INFO.WALLET_PASSPHRASE,
};
await basecoin.recover(recoveryOptions).should.rejectedWith('insufficient balance to build the transaction');
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3R4LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L3N0eC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG9EQUE0QjtBQUM1QixnREFBd0I7QUFFeEIsNENBQTBDO0FBQzFDLDhDQUF5QztBQUN6Qyw4Q0FBMEQ7QUFDMUQsNENBQXVDO0FBQ3ZDLHVEQUFrRDtBQUVsRCxzREFBd0M7QUFDeEMsbUNBQThDO0FBRzlDLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxZQUFNLENBQUM7QUFFM0IsUUFBUSxDQUFDLE1BQU0sRUFBRTtJQUNmLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQztJQUN2QixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUM7SUFDNUIsSUFBSSxLQUFtQixDQUFDO0lBQ3hCLElBQUksUUFBUSxDQUFDO0lBRWIsTUFBTSxpQkFBaUIsR0FBRztRQUN4QixFQUFFO1FBQ0YsSUFBSTtRQUNKLEtBQUs7UUFDTCwwQ0FBMEM7UUFDMUMsMkNBQTJDO0tBQzVDLENBQUM7SUFFRixNQUFNLGFBQWEsR0FBRztRQUNwQiwwQ0FBMEM7UUFDMUMsMkNBQTJDO1FBQzNDLDJDQUEyQztRQUMzQywyQ0FBMkM7UUFDM0Msb0RBQW9EO1FBQ3BELG9EQUFvRDtLQUNyRCxDQUFDO0lBRUYsTUFBTSxDQUFDO1FBQ0wsS0FBSyxHQUFHLG9CQUFTLENBQUMsUUFBUSxDQUFDLGtCQUFRLEVBQUU7WUFDbkMsR0FBRyxFQUFFLE1BQU07U0FDWixDQUFDLENBQUM7UUFDSCxLQUFLLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUMzQixLQUFLLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxTQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDOUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsVUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ2hELFFBQVEsR0FBRyxL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QUFDLEdBQUcsRUFBRSxjQUFjLENBQUMsQ0FBQztZQUM5QixJQUFBLGNBQUksRUFBQyw2QkFBNkIsQ0FBQztpQkFDaEMsR0FBRyxDQUFDLHdCQUF3QixXQUFXLFNBQVMsQ0FBQztpQkFDakQsS0FBSyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsc0JBQXNCLENBQUMsQ0FBQztZQUMvQyxNQUFNLGNBQWMsR0FBRyxRQUFRLENBQUMsc0JBQXNCLENBQUM7WUFDdkQsY0FBYyxDQUFDLG1CQUFtQjtnQkFDaEMsb0lBQW9JLENBQUM7WUFDdkksSUFBQSxjQUFJLEVBQUMsNkJBQTZCLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLENBQUM7aUJBQ3pELElBQUksQ0FBQyxzQkFBc0IsRUFBRSxjQUFjLENBQUM7aUJBQzVDLEtBQUssQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLHVCQUF1QixDQUFDLENBQUM7WUFDaEQsTUFBTSxlQUFlLEdBQW9CO2dCQUN2QyxTQUFTLEVBQUUsUUFBUSxDQUFDLHdCQUF3QixDQUFDLFVBQVU7Z0JBQ3ZELE9BQU8sRUFBRSxRQUFRLENBQUMsd0JBQXdCLENBQUMsUUFBUTtnQkFDbkQsV0FBVyxFQUFFLFdBQVc7Z0JBQ3hCLG1CQUFtQixFQUFFLFFBQVEsQ0FBQyx1QkFBdUI7Z0JBQ3JELFFBQVEsRUFBRSxRQUFRLENBQUMsd0JBQXdCLENBQUMsYUFBYTtnQkFDekQsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLHdCQUF3QixDQUFDLGlCQUFpQjthQUN0RSxDQUFDO1lBQ0YsTUFBTSxRQUFRLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsK0NBQStDLENBQUMsQ0FBQztRQUMvRyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgbm9jayBmcm9tICdub2NrJztcblxuaW1wb3J0IHsgQml0R29BUEkgfSBmcm9tICdAYml0Z28vc2RrLWFwaSc7XG5pbXBvcnQgeyBXYWxsZXQgfSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgVGVzdEJpdEdvLCBUZXN0Qml0R29BUEkgfSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuaW1wb3J0IHsgY29pbnMgfSBmcm9tICdAYml0Z28vc3RhdGljcyc7XG5pbXBvcnQgeyBjdlRvU3RyaW5nIH0gZnJvbSAnQHN0YWNrcy90cmFuc2FjdGlvbnMnO1xuXG5pbXBvcnQgKiBhcyB0ZXN0RGF0YSBmcm9tICcuLi9maXh0dXJlcyc7XG5pbXBvcnQgeyBTdHgsIFN0eExpYiwgVHN0eCB9IGZyb20gJy4uLy4uL3NyYyc7XG5pbXBvcnQgeyBSZWNvdmVyeUluZm8sIFJlY292ZXJ5T3B0aW9ucywgUmVjb3ZlcnlUcmFuc2FjdGlvbiB9IGZyb20gJy4uLy4uL3NyYy9saWIvaWZhY2UnO1xuXG5jb25zdCB7IEtleVBhaXIgfSA9IFN0eExpYjtcblxuZGVzY3JpYmUoJ1NUWDonLCBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IGNvaW5OYW1lID0gJ3N0eCc7XG4gIGNvbnN0IGNvaW5OYW1lVGVzdCA9ICd0c3R4JztcbiAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gIGxldCBiYXNlY29pbjtcblxuICBjb25zdCBiYWRWYWxpZEFkZHJlc3NlcyA9IFtcbiAgICAnJyxcbiAgICBudWxsLFxuICAgICdhYmMnLFxuICAgICdTUDI0NEhZUFlBVDJCQjJRRTUxM05TUDgxSFRNWVdCSlAwMkhQR0s2JyxcbiAgICAnU1QxVDc1OEs2VDJZUktHOVEwVEoxNkI2RlA1UVFSRVdaU0VTUlMwUFknLFxuICBdO1xuXG4gIGNvbnN0IGdvb2RBZGRyZXNzZXMgPSBbXG4gICAgJ1NUQjQ0SFlQWUFUMkJCMlFFNTEzTlNQODFIVE1ZV0JKUDAySFBHSzYnLFxuICAgICdTVDExTkpUVEtHVlQ2RDFIWTROSlJWUVdNUU03VFZBUjA5MUVKOFAyWScsXG4gICAgJ1NQMlQ3NThLNlQyWVJLRzlRMFRKMTZCNkZQNVFRUkVXWlNFU1JTMFBZJyxcbiAgICAnU00zVzVRRldHUEcxSkM4UjI1RVZaREVQM0JFU0paODMxSlBOTlFGVFonLFxuICAgICdTTTNXNVFGV0dQRzFKQzhSMjVFVlpERVAzQkVTSlo4MzFKUE5OUUZUWj9tZW1vSWQ9MScsXG4gICAgJ1NUMVdWSk1TNVZTNDFGMFlNSDdEMk0wVkhYUkc0Q1k0M1pKWkJTNjBBP21lbW9JZD00JyxcbiAgXTtcblxuICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7XG4gICAgICBlbnY6ICdtb2NrJyxcbiAgICB9KTtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICBiaXRnby5zYWZlUmVnaXN0ZXIoJ3N0eCcsIFN0eC5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0c3R4JywgVHN0eC5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYmFzZWNvaW4gPSBiaXRnby5jb2luKGNvaW5OYW1lVGVzdCk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiBCdWlsZCBhbiB1bnNpZ25lZCBhY2NvdW50LWxpYiBzaWdubGUtc2lnbmF0dXJlIHNlbmQgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIGRlc3RpbmF0aW9uIFRoZSBkZXN0aW5hdGlvbiBhZGRyZXNzIG9mIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0gYW1vdW50IFRoZSBhbW91bnQgdG8gc2VuZCB0byB0aGUgcmVjaXBpZW50XG4gICAqL1xuICBjb25zdCBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24gPSBhc3luYyBmdW5jdGlvbiAoeyBkZXN0aW5hdGlvbiwgYW1vdW50ID0gJzEwMDAwMCcsIHB1YmxpY0tleSwgbWVtbyA9ICcnIH0pIHtcbiAgICBjb25zdCBmYWN0b3J5ID0gbmV3IFN0eExpYi5UcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW5zLmdldChjb2luTmFtZSkpO1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgdHhCdWlsZGVyLmZlZSh7XG4gICAgICBmZWU6ICcxODAnLFxuICAgIH0pO1xuICAgIHR4QnVpbGRlci50byhkZXN0aW5hdGlvbik7XG4gICAgdHhCdWlsZGVyLmFtb3VudChhbW91bnQpO1xuICAgIHR4QnVpbGRlci5ub25jZSgxKTtcbiAgICB0eEJ1aWxkZXIuZnJvbVB1YktleShwdWJsaWNLZXkpO1xuICAgIHR4QnVpbGRlci5tZW1vKG1lbW8pO1xuICAgIHR4QnVpbGRlci5udW1iZXJTaWduYXR1cmVzKDEpO1xuICAgIHJldHVybiBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgfTtcblxuICAvKipcbiAgICogQnVpbGQgYW4gdW5zaWduZWQgYWNjb3VudC1saWIgbXVsdGktc2lnbmF0dXJlIHNlbmQgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIGRlc3RpbmF0aW9uIFRoZSBkZXN0aW5hdGlvbiBhZGRyZXNzIG9mIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0gYW1vdW50IFRoZSBhbW91bnQgdG8gc2VuZCB0byB0aGUgcmVjaXBpZW50XG4gICAqL1xuICBjb25zdCBidWlsZG11bHRpU2lnVW5zaWduZWRUcmFuc2FjdGlvbiA9IGFzeW5jIGZ1bmN0aW9uICh7IGRlc3RpbmF0aW9uLCBhbW91bnQgPSAnMTAwMDAwJywgcHVibGljS2V5cywgbWVtbyA9ICcnIH0pIHtcbiAgICBjb25zdCBmYWN0b3J5ID0gbmV3IFN0eExpYi5UcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW5zLmdldChjb2luTmFtZSkpO1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgdHhCdWlsZGVyLmZlZSh7XG4gICAgICBmZWU6ICcxODAnLFxuICAgIH0pO1xuICAgIHR4QnVpbGRlci50byhkZXN0aW5hdGlvbik7XG4gICAgdHhCdWlsZGVyLmFtb3VudChhbW91bnQpO1xuICAgIHR4QnVpbGRlci5ub25jZSgxKTtcbiAgICB0eEJ1aWxkZXIuZnJvbVB1YktleShwdWJsaWNLZXlzKTtcbiAgICB0eEJ1aWxkZXIubnVtYmVyU2lnbmF0dXJlcygyKTtcbiAgICB0eEJ1aWxkZXIubWVtbyhtZW1vKTtcbiAgICByZXR1cm4gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gIH07XG5cbiAgaXQoJ3Nob3VsZCBpbnN0YW50aWF0ZSB0aGUgY29pbicsIGZ1bmN0aW9uICgpIHtcbiAgICBsZXQgbG9jYWxCYXNlY29pbiA9IGJpdGdvLmNvaW4oJ3RzdHgnKTtcbiAgICBsb2NhbEJhc2Vjb2luLnNob3VsZC5iZS5hbi5pbnN0YW5jZW9mKFRzdHgpO1xuXG4gICAgbG9jYWxCYXNlY29pbiA9IGJpdGdvLmNvaW4oJ3N0eCcpO1xuICAgIGxvY2FsQmFzZWNvaW4uc2hvdWxkLmJlLmFuLmluc3RhbmNlb2YoU3R4KTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBjaGVjayB2YWxpZCBhZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgYmFkVmFsaWRBZGRyZXNzZXMubWFwKChhZGRyKSA9PiB7XG4gICAgICBiYXNlY29pbi5pc1ZhbGlkQWRkcmVzcyhhZGRyKS5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgIH0pO1xuICAgIGdvb2RBZGRyZXNzZXMubWFwKChhZGRyKSA9PiB7XG4gICAgICBiYXNlY29pbi5pc1ZhbGlkQWRkcmVzcyhhZGRyKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdmVyaWZ5IGlzV2FsbGV0QWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB1c2VyS2V5ID0ge1xuICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0dTMkhNZHZBTk43bzhFU1dxd3ZyNVU0cnk1ZlpkRDlWSGh5bVd5Zm9EUUY0dnpmS290WGdHdEpUcndyRlJ6N1hiR0ZvdjRGcWRLS282bVJZTld2TXA3UDIzRGp1Sm5TJyxcbiAgICB9O1xuICAgIGNvbnN0IGJhY2t1cEtleSA9IHtcbiAgICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNGRXpyNUNjcEZ6UEc0NXJtUGY3NURUdkRvYk41Z0ppbUNhdGJIdHpSNTNTYkh6RFoxSjU2YnlLU3NkYzh2U3VqR3VRcHlQamI3THN1YTJOZkFESmV3UHhOekwzTjZUaicsXG4gICAgfTtcbiAgICBjb25zdCBiaXRnb0tleSA9IHtcbiAgICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNHUDFhZGszNFZ6UlFKRU1YMjVyQ3hqRXlVOVlGRldOaFdOendQb3FnakxvS2ZucW90THdyejdrQmV2V2JSWm5xVFNRclFEdUp1WVVRYURRNUREUEV6RVhNd1BTOVBFZicsXG4gICAgfTtcbiAgICBjb25zdCBrZXljaGFpbnMgPSBbdXNlcktleSwgYmFja3VwS2V5LCBiaXRnb0tleV07XG4gICAgY29uc3QgdmFsaWRBZGRyZXNzMSA9ICdTTkFZUUZaNkVGNTRENVhXSlAzR0FFMVk4RFBZWEtGQzdUVE1ZWEZWJztcbiAgICBjb25zdCB2YWxpZEFkZHJlc3MyID0gJ1NOQVlRRlo2RUY1NEQ1WFdKUDNHQUUxWThEUFlYS0ZDN1RUTVlYRlY/bWVtb0lkPTInO1xuICAgIGNvbnN0IHVucmVsYXRlZFZhbGlkQWRkcmVzcyA9ICdTVDExTkpUVEtHVlQ2RDFIWTROSlJWUVdNUU03VFZBUjA5MUVKOFAyWT9tZW1vSWQ9MSc7XG4gICAgY29uc3QgaW52YWxpZEFkZHJlc3MgPSAnU1QxVDc1OEs2VDJZUktHOVEwVEoxNkI2RlA1UVFSRVdaU0VTUlMwUFknO1xuICAgIChhd2FpdCBiYXNlY29pbi5pc1dhbGxldEFkZHJlc3MoeyBhZGRyZXNzOiB2YWxpZEFkZHJlc3MxLCBrZXljaGFpbnMgfSkpLnNob3VsZC50cnVlKCk7XG4gICAgKGF3YWl0IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7IGFkZHJlc3M6IHZhbGlkQWRkcmVzczIsIGtleWNoYWlucyB9KSkuc2hvdWxkLnRydWUoKTtcbiAgICAoYXdhaXQgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHsgYWRkcmVzczogdW5yZWxhdGVkVmFsaWRBZGRyZXNzLCBrZXljaGFpbnMgfSkpLnNob3VsZC5mYWxzZSgpO1xuXG4gICAgYXNzZXJ0LnJlamVjdHMoXG4gICAgICBhc3luYyAoKSA9PiBiYXNlY29pbi5pc1dhbGxldEFkZHJlc3MoeyBhZGRyZXNzOiBpbnZhbGlkQWRkcmVzcywga2V5Y2hhaW5zIH0pLFxuICAgICAgYGludmFsaWQgYWRkcmVzcyAke2ludmFsaWRBZGRyZXNzfWBcbiAgICApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGV4cGxhaW4gYSB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBleHBsYWluID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgIHR4SGV4OiB0ZXN0RGF0YS50eEZvckV4cGxhaW5UcmFuc2ZlcixcbiAgICAgIGZlZUluZm86IHsgZmVlOiAnJyB9LFxuICAgIH0pO1xuICAgIGV4cGxhaW4uaWQuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnR4RXhwbGFpbmVkVHJhbnNmZXIuaWQpO1xuICAgIGV4cGxhaW4ub3V0cHV0QW1vdW50LnNob3VsZC5lcXVhbCh0ZXN0RGF0YS50eEV4cGxhaW5lZFRyYW5zZmVyLm91dHB1dEFtb3VudCk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwodGVzdERhdGEudHhFeHBsYWluZWRUcmFuc2Zlci5vdXRwdXRBbW91bnQpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS50eEV4cGxhaW5lZFRyYW5zZmVyLnJlY2lwaWVudCk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLm1lbW8uc2hvdWxkLmVxdWFsKHRlc3REYXRhLnR4RXhwbGFpbmVkVHJhbnNmZXIubWVtbyk7XG4gICAgZXhwbGFpbi5mZWUuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnR4RXhwbGFpbmVkVHJhbnNmZXIuZmVlKTtcbiAgICBleHBsYWluLmNoYW5nZUFtb3VudC5zaG91bGQuZXF1YWwoJzAnKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBleHBsYWluIGFuIHVuc2lnbmVkIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGtleSA9IG5ldyBLZXlQYWlyKCk7XG4gICAgY29uc3QgZGVzdGluYXRpb24gPSAnU1QxMU5KVFRLR1ZUNkQxSFk0TkpSVlFXTVFNN1RWQVIwOTFFSjhQMlknO1xuICAgIGNvbnN0IGFtb3VudCA9ICcxMDAwMDAnO1xuICAgIGNvbnN0IG1lbW8gPSAnaSBjYW5ub3QgYmUgYnJvYWRjYXN0JztcblxuICAgIGNvbnN0IHVuc2lnbmVkVHJhbnNhY3Rpb24gPSBhd2FpdCBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24oe1xuICAgICAgZGVzdGluYXRpb24sXG4gICAgICBhbW91bnQsXG4gICAgICBwdWJsaWNLZXk6IGtleS5nZXRLZXlzKCkucHViLFxuICAgICAgbWVtbzogbWVtbyxcbiAgICB9KTtcbiAgICBjb25zdCB1bnNpZ25lZEhleCA9IHVuc2lnbmVkVHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgdHhIZXg6IHVuc2lnbmVkSGV4LFxuICAgICAgcHVibGljS2V5czogW2tleS5nZXRLZXlzKCkucHViXSxcbiAgICAgIGZlZUluZm86IHsgZmVlOiAnJyB9LFxuICAgIH0pO1xuXG4gICAgZXhwbGFpbi5tZW1vLnNob3VsZC5lcXVhbChtZW1vKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbChhbW91bnQpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbChkZXN0aW5hdGlvbik7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgZXhwbGFpbiB1bnNpZ25lZCB0cmFuc2ZlciB0cmFuc2FjdGlvbiBoZXgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICB0eEhleDogdGVzdERhdGEudW5zaWduZWRUeEZvckV4cGxhaW5UcmFuc2ZlcixcbiAgICAgIHB1YmxpY0tleXM6IFsnMDM3OTdkZDY1MzA0MGQzNDRmZDA0OGMxYWQwNWQ0Y2JjYjIxNzhiMzBjNmEwYzQyNzY5OTQ3OTVmM2U4MzNkYTQxJ10sXG4gICAgICBmZWVJbmZvOiB7IGZlZTogJycgfSxcbiAgICB9KTtcbiAgICBleHBsYWluLm91dHB1dEFtb3VudC5zaG91bGQuZXF1YWwodGVzdERhdGEudW5zaWduZWRUeEV4cGxhaW5lZFRyYW5zZmVyLm91dHB1dEFtb3VudCk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwodGVzdERhdGEudW5zaWduZWRUeEV4cGxhaW5lZFRyYW5zZmVyLm91dHB1dEFtb3VudCk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKHRlc3REYXRhLnVuc2lnbmVkVHhFeHBsYWluZWRUcmFuc2Zlci5yZWNpcGllbnQpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5tZW1vLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS51bnNpZ25lZFR4RXhwbGFpbmVkVHJhbnNmZXIubWVtbyk7XG4gICAgZXhwbGFpbi5mZWUuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnVuc2lnbmVkVHhFeHBsYWluZWRUcmFuc2Zlci5mZWUpO1xuICAgIGV4cGxhaW4uY2hhbmdlQW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGV4cGxhaW4gYSBjb250cmFjdCBjYWxsIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgdHhIZXg6IHRlc3REYXRhLnR4Rm9yRXhwbGFpbkNvbnRyYWN0LFxuICAgICAgZmVlSW5mbzogeyBmZWU6ICcnIH0sXG4gICAgfSk7XG4gICAgZXhwbGFpbi5pZC5zaG91bGQuZXF1YWwodGVzdERhdGEudHhFeHBsYWluZWRDb250cmFjdC5pZCk7XG4gICAgZXhwbGFpbi5mZWUuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnR4RXhwbGFpbmVkQ29udHJhY3QuZmVlKTtcbiAgICBleHBsYWluLmNvbnRyYWN0QWRkcmVzcy5zaG91bGQuZXF1YWwodGVzdERhdGEudHhFeHBsYWluZWRDb250cmFjdC5jb250cmFjdEFkZHJlc3MpO1xuICAgIGV4cGxhaW4uY29udHJhY3ROYW1lLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS50eEV4cGxhaW5lZENvbnRyYWN0LmNvbnRyYWN0TmFtZSk7XG4gICAgZXhwbGFpbi5jb250cmFjdEZ1bmN0aW9uLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS50eEV4cGxhaW5lZENvbnRyYWN0LmZ1bmN0aW9uTmFtZSk7XG4gICAgZXhwbGFpbi5jb250cmFjdEZ1bmN0aW9uQXJnc1swXS50eXBlLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS50eEV4cGxhaW5lZENvbnRyYWN0LmZ1bmN0aW9uQXJnc1swXS50eXBlKTtcbiAgICBleHBsYWluLmNvbnRyYWN0RnVuY3Rpb25BcmdzWzBdLnZhbHVlLnRvU3RyaW5nKCkuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnR4RXhwbGFpbmVkQ29udHJhY3QuZnVuY3Rpb25BcmdzWzBdLnZhbHVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBleHBsYWluIGEgZnVuZ2libGUgdG9rZW4gdHJhbnNmZXIgdHJhbnNhY3Rpb24gd2l0aCBtZW1vJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgdHhIZXg6IHRlc3REYXRhLnR4Rm9yRXhwbGFpbkZ1bmdpYmxlVG9rZW5UcmFuc2ZlcixcbiAgICAgIGZlZUluZm86IHsgZmVlOiAnJyB9LFxuICAgIH0pO1xuICAgIGV4cGxhaW4uaWQuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmZ1bmdpYmxlVG9rZW5UcmFuc2ZlclR4LmlkKTtcbiAgICBleHBsYWluLmZlZS5zaG91bGQuZXF1YWwodGVzdERhdGEuZnVuZ2libGVUb2tlblRyYW5zZmVyVHguZmVlKTtcbiAgICBleHBsYWluLm1lbW8uc2hvdWxkLmVxdWFsKCcxJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRBbW91bnQuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmZ1bmdpYmxlVG9rZW5UcmFuc2ZlclR4LmZ1bmN0aW9uQXJnc1syXS52YWx1ZSk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwodGVzdERhdGEuZnVuZ2libGVUb2tlblRyYW5zZmVyVHguZnVuY3Rpb25BcmdzWzJdLnZhbHVlKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoY3ZUb1N0cmluZyh0ZXN0RGF0YS5mdW5naWJsZVRva2VuVHJhbnNmZXJUeC5mdW5jdGlvbkFyZ3NbMV0pKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0ubWVtby5zaG91bGQuZXF1YWwoJzEnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0udG9rZW5OYW1lLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5mdW5naWJsZVRva2VuVHJhbnNmZXJUeC50b2tlbk5hbWUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGV4cGxhaW4gYSBmdW5naWJsZSB0b2tlbiB0cmFuc2ZlciB0cmFuc2FjdGlvbiB3aXRob3V0IG1lbW8nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICB0eEhleDogdGVzdERhdGEudHhGb3JFeHBsYWluRnVuZ2libGVUb2tlblRyYW5zZmVyV2l0aG91dE1lbW8sXG4gICAgICBmZWVJbmZvOiB7IGZlZTogJycgfSxcbiAgICB9KTtcbiAgICBleHBsYWluLmlkLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5oZXhXaXRob3V0TWVtb1RyYW5zZmVySWQpO1xuICAgIGV4cGxhaW4uZmVlLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5mdW5naWJsZVRva2VuVHJhbnNmZXJUeC5mZWUpO1xuICAgIGFzc2VydC5kZWVwRXF1YWwoZXhwbGFpbi5tZW1vLCB1bmRlZmluZWQsICdtZW1vIHNob3VsZCBiZSB1bmRlZmluZWQnKTtcbiAgICBleHBsYWluLm91dHB1dEFtb3VudC5zaG91bGQuZXF1YWwodGVzdERhdGEuZnVuZ2libGVUb2tlblRyYW5zZmVyVHguZnVuY3Rpb25BcmdzWzJdLnZhbHVlKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5mdW5naWJsZVRva2VuVHJhbnNmZXJUeC5mdW5jdGlvbkFyZ3NbMl0udmFsdWUpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbChjdlRvU3RyaW5nKHRlc3REYXRhLmZ1bmdpYmxlVG9rZW5UcmFuc2ZlclR4LmZ1bmN0aW9uQXJnc1sxXSkpO1xuICAgIGFzc2VydC5kZWVwRXF1YWwoZXhwbGFpbi5vdXRwdXRzWzBdLm1lbW8sIHVuZGVmaW5lZCwgJ21lbW8gc2hvdWxkIGJlIHVuZGVmaW5lZCcpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS50b2tlbk5hbWUuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmZ1bmdpYmxlVG9rZW5UcmFuc2ZlclR4LnRva2VuTmFtZSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdLZXlwYWlyczonLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBhIGtleXBhaXIgZnJvbSByYW5kb20gc2VlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBiYXNlY29pbi5nZW5lcmF0ZUtleVBhaXIoKTtcbiAgICAgIGtleVBhaXIuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3B1YicpO1xuICAgICAga2V5UGFpci5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncHJ2Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGEga2V5cGFpciBmcm9tIGEgc2VlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNlZWRUZXh0ID1cbiAgICAgICAgJzgwMzUwYjQyMDhkMzgxZmJmZTIyNzZhMzI2NjAzMDQ5ZmU1MDA3MzFjNDZkM2M5OTM2YjVjZTAzNmI1MTM3N2YyNGJhYjdkZDBjMmFmN2YxMDc0MTZlZjg1OGZmNzliMDY3MGM3MjQwNmRhZDA2NGU3MmJiMTdmYzBhOTAzOGJiJztcbiAgICAgIGNvbnN0IHNlZWQgPSBCdWZmZXIuZnJvbShzZWVkVGV4dCwgJ2hleCcpO1xuICAgICAgY29uc3Qga2V5UGFpciA9IGJhc2Vjb2luLmdlbmVyYXRlS2V5UGFpcihzZWVkKTtcbiAgICAgIGtleVBhaXIucHViLnNob3VsZC5lcXVhbChcbiAgICAgICAgJ3hwdWI2NjFNeU13QXFSYmNGQXdxdlNHYmszNWtKZjdDUXFkTjF3NENNVUJCVHFINWUzaXZqVTZEOHVndjloUlNnUmJSZW5DNHczYWhYZExWYWh3amdqWGhTdVFLTWROZG41NVk5VE5TYWdCa3R3cydcbiAgICAgICk7XG4gICAgICBrZXlQYWlyLnBydi5zaG91bGQuZXF1YWwoXG4gICAgICAgICd4cHJ2OXMyMVpyUUgxNDNLMmdzTnBRamJOdTkxa2RHaTFOdVdlaThiWjVtWnVWazZtRlBuQnZteGI3TlNKUWRiWlczRkdwSzNZY243am9yQVhjRXpNdnZpR3RieUJ6NXRCcmpmbld5UXAzZzc1RksnXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2lnbiB0cmFuc2FjdGlvbjonLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBzaWduIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5ID0gbmV3IEtleVBhaXIoe1xuICAgICAgICBwcnY6ICcyMWQ0M2QyYWUwZGExZDlkMDRjZmNhYWM3ZDM5N2EzMzczMzg4MTA4MWYwYjJjZDAzODA2MmNmMGNjYmI3NTI2MDEnLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBkZXN0aW5hdGlvbiA9ICdTVERFN1k4SFYzUlg4VkJNMlRaVldKVFM3WkExWEIwU1NDM05FVkgwJztcbiAgICAgIGNvbnN0IGFtb3VudCA9ICcxMDAwMDAnO1xuXG4gICAgICBjb25zdCB1bnNpZ25lZFRyYW5zYWN0aW9uID0gYXdhaXQgYnVpbGRVbnNpZ25lZFRyYW5zYWN0aW9uKHtcbiAgICAgICAgZGVzdGluYXRpb24sXG4gICAgICAgIGFtb3VudCxcbiAgICAgICAgcHVibGljS2V5OiBrZXkuZ2V0S2V5cygpLnB1YixcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICBwcnY6IGtleS5nZXRLZXlzKCkucHJ2IS50b1N0cmluZygpLFxuICAgICAgICBwdWJLZXlzOiBba2V5LmdldEtleXMoKS5wdWJdLFxuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHVuc2lnbmVkVHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgZmFjdG9yeSA9IG5ldyBTdHhMaWIuVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2lucy5nZXQoY29pbk5hbWUpKTtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZnJvbSh0eC5oYWxmU2lnbmVkLnR4SGV4KTtcbiAgICAgIGNvbnN0IHNpZ25lZFR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCB0eEpzb24gPSBzaWduZWRUeC50b0pzb24oKTtcbiAgICAgIHR4SnNvbi5wYXlsb2FkLnRvLnNob3VsZC5lcXVhbChkZXN0aW5hdGlvbik7XG4gICAgICB0eEpzb24ucGF5bG9hZC5hbW91bnQuc2hvdWxkLmVxdWFsKGFtb3VudCk7XG4gICAgICBzaWduZWRUeC5zaWduYXR1cmUubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2lnbiBtdWx0aXNpZyB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleTEgPSBuZXcgS2V5UGFpcih7XG4gICAgICAgIHBydjogJzIxZDQzZDJhZTBkYTFkOWQwNGNmY2FhYzdkMzk3YTMzNzMzODgxMDgxZjBiMmNkMDM4MDYyY2YwY2NiYjc1MjYwMScsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGtleTIgPSBuZXcgS2V5UGFpcih7XG4gICAgICAgIHBydjogJ2M3MTcwMGIwN2Q1MjBhOGM5NzMxZTRkMGYwOTVhYTZlZmI5MWUxNmUyNWZiMjdjZTJiNzJlN2I2OThmODEyN2EwMScsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGtleTMgPSBuZXcgS2V5UGFpcih7XG4gICAgICAgIHBydjogJ2U3NWRjYjY2Zjg0Mjg3ZWFmMzQ3OTU1ZTk0ZmEwNDMzNzI5OGRiZDk1YWEwZGJiOTg1NzcxMTA0ZWYxOTEzZGIwMScsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGRlc3RpbmF0aW9uID0gJ1NUREU3WThIVjNSWDhWQk0yVFpWV0pUUzdaQTFYQjBTU0MzTkVWSDAnO1xuICAgICAgY29uc3QgYW1vdW50ID0gJzEwMDAwMCc7XG4gICAgICBjb25zdCBwdWJsaWNLZXlzID0gW2tleTEuZ2V0S2V5cyh0cnVlKS5wdWIsIGtleTIuZ2V0S2V5cyh0cnVlKS5wdWIsIGtleTMuZ2V0S2V5cyh0cnVlKS5wdWJdO1xuICAgICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJ1aWxkbXVsdGlTaWdVbnNpZ25lZFRyYW5zYWN0aW9uKHtcbiAgICAgICAgZGVzdGluYXRpb24sXG4gICAgICAgIGFtb3VudCxcbiAgICAgICAgcHVibGljS2V5cyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICBwcnY6IFtcbiAgICAgICAgICAnMjFkNDNkMmFlMGRhMWQ5ZDA0Y2ZjYWFjN2QzOTdhMzM3MzM4ODEwODFmMGIyY2QwMzgwNjJjZjBjY2JiNzUyNjAxJyxcbiAgICAgICAgICAnYzcxNzAwYjA3ZDUyMGE4Yzk3MzFlNGQwZjA5NWFhNmVmYjkxZTE2ZTI1ZmIyN2NlMmI3MmU3YjY5OGY4MTI3YTAxJyxcbiAgICAgICAgXSxcbiAgICAgICAgcHViS2V5czogW2tleTEuZ2V0S2V5cygpLnB1Yiwga2V5Mi5nZXRLZXlzKCkucHViLCBrZXkzLmdldEtleXMoKS5wdWJdLFxuICAgICAgICBudW1iZXJTaWduYXR1cmU6IDIsXG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogdW5zaWduZWRUcmFuc2FjdGlvbi50b0Jyb2FkY2FzdEZvcm1hdCgpLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBjb25zdCBmYWN0b3J5ID0gbmV3IFN0eExpYi5UcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW5zLmdldChjb2luTmFtZSkpO1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5mcm9tKHR4LnR4SGV4KTtcbiAgICAgIGNvbnN0IHNpZ25lZFR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCB0eEpzb24gPSBzaWduZWRUeC50b0pzb24oKTtcbiAgICAgIHR4SnNvbi5wYXlsb2FkLnRvLnNob3VsZC5lcXVhbChkZXN0aW5hdGlvbik7XG4gICAgICB0eEpzb24ucGF5bG9hZC5hbW91bnQuc2hvdWxkLmVxdWFsKGFtb3VudCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdnZXRTaWduaW5nUGF5bG9hZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiB0aGUgdHggYXMgYSBidWZmZXInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBub25UU1NDb2luID0gYml0Z28uY29pbigndHN0eCcpO1xuICAgICAgY29uc3QgYnVmZmVyVHggPSBhd2FpdCBub25UU1NDb2luLmdldFNpZ25hYmxlUGF5bG9hZCh0ZXN0RGF0YS51bnNpZ25lZFR4Rm9yRXhwbGFpblRyYW5zZmVyKTtcbiAgICAgIGJ1ZmZlclR4LnNob3VsZC5iZS5kZWVwRXF1YWwoQnVmZmVyLmZyb20odGVzdERhdGEudW5zaWduZWRUeEZvckV4cGxhaW5UcmFuc2ZlcikpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVmVyaWZ5IFRyYW5zYWN0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGFkZHJlc3MxID0gJzB4MTc0Y2ZkODIzYWY4Y2UyN2VkMGFmZWUzZmNmM2MzYmEyNTkxMTZiZSc7XG4gICAgY29uc3QgYWRkcmVzczIgPSAnMHg3ZTg1YmRjMjdjMDUwZTM5MDVlYmY0YjhlNjM0ZDlhZDZlZGQwZGU2JztcbiAgICBpdCgnc2hvdWxkIHJlamVjdCBhIHR4UHJlYnVpbGQgd2l0aCBtb3JlIHRoYW4gb25lIHJlY2lwaWVudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfSxcbiAgICAgICAgICB7IGFtb3VudDogJzI1MDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMiB9LFxuICAgICAgICBdLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgIGB0c3R4IGRvZXNuJ3Qgc3VwcG9ydCBzZW5kaW5nIHRvIG1vcmUgdGhhbiAxIGRlc3RpbmF0aW9uIGFkZHJlc3Mgd2l0aGluIGEgc2luZ2xlIHRyYW5zYWN0aW9uLiBUcnkgYWdhaW4sIHVzaW5nIG9ubHkgYSBzaW5nbGUgcmVjaXBpZW50LmBcbiAgICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JlY292ZXIgVHJhbnNhY3Rpb24gU1RYJywgZnVuY3Rpb24gKCkge1xuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICBub2NrLmVuYWJsZU5ldENvbm5lY3QoKTtcbiAgICB9KTtcbiAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICB9KTtcbiAgICBhZnRlcihmdW5jdGlvbiAoKSB7XG4gICAgICBub2NrLmRpc2FibGVOZXRDb25uZWN0KCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc2lnbmVkIHJlY292ZXIgdHJhbnNhY3Rpb24gd2hlbiBwcml2YXRlIGtleSBkYXRhIGlzIHBhc3NlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJvb3RBZGRyZXNzID0gdGVzdERhdGEuSE9UX1dBTExFVF9ST09UX0FERFJFU1M7XG4gICAgICBub2NrKGBodHRwczovL2FwaS50ZXN0bmV0Lmhpcm8uc29gKVxuICAgICAgICAuZ2V0KGAvZXh0ZW5kZWQvdjIvYWRkcmVzc2VzLyR7cm9vdEFkZHJlc3N9L2JhbGFuY2VzL3N0eGApXG4gICAgICAgIC5yZXBseSgyMDAsIHRlc3REYXRhLkFDQ09VTlRfQkFMQU5DRV9SRVNQT05TRSk7XG4gICAgICBub2NrKGBodHRwczovL2FwaS50ZXN0bmV0Lmhpcm8uc29gKVxuICAgICAgICAuZ2V0KGAvZXh0ZW5kZWQvdjEvYWRkcmVzcy8ke3Jvb3RBZGRyZXNzfS9ub25jZXNgKVxuICAgICAgICAucmVwbHkoMjAwLCB0ZXN0RGF0YS5BQ0NPVU5UX05PTkNFX1JFU1BPTlNFKTtcbiAgICAgIG5vY2soYGh0dHBzOi8vYXBpLnRlc3RuZXQuaGlyby5zb2AsIHsgYWxsb3dVbm1vY2tlZDogdHJ1ZSB9KVxuICAgICAgICAucG9zdChgL3YyL2ZlZXMvdHJhbnNhY3Rpb25gLCB0ZXN0RGF0YS5GRUVfRVNUSU1BVElPTl9SRVFVRVNUKVxuICAgICAgICAucmVwbHkoMjAwLCB0ZXN0RGF0YS5GRUVfRVNUSU1BVElPTl9SRVNQT05TRSk7XG5cbiAgICAgIGNvbnN0IHJlY292ZXJ5T3B0aW9uczogUmVjb3ZlcnlPcHRpb25zID0ge1xuICAgICAgICBiYWNrdXBLZXk6IHRlc3REYXRhLkhPVF9XQUxMRVRfS0VZX0NBUkRfSU5GTy5CQUNLVVBfS0VZLFxuICAgICAgICB1c2VyS2V5OiB0ZXN0RGF0YS5IT1RfV0FMTEVUX0tFWV9DQVJEX0lORk8uVVNFUl9LRVksXG4gICAgICAgIHJvb3RBZGRyZXNzOiByb290QWRkcmVzcyxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogdGVzdERhdGEuREVTVElOQVRJT05fQUREUkVTU19XUlcsXG4gICAgICAgIGJpdGdvS2V5OiB0ZXN0RGF0YS5IT1RfV0FMTEVUX0tFWV9DQVJEX0lORk8uQklUR09fUFVCX0tFWSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogdGVzdERhdGEuSE9UX1dBTExFVF9LRVlfQ0FSRF9JTkZPLldBTExFVF9QQVNTUEhSQVNFLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlOiBSZWNvdmVyeVRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4ucmVjb3ZlcihyZWNvdmVyeU9wdGlvbnMpO1xuICAgICAgcmVzcG9uc2Uuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG4gICAgICBhc3NlcnQuZGVlcEVxdWFsKHJlc3BvbnNlLnR4SGV4LCB0ZXN0RGF0YS5IT1RfV0FMTEVUX1JFQ09WRVJZX1RYX0hFWCwgJ3R4IGhleCBub3QgbWF0Y2hpbmchJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGFuIHVuc2lnbmVkIHRyYW5zYWN0aW9uIHdoZW4gcHVibGljIGtleXMgYXJlIHBhc3NlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJvb3RBZGRyZXNzID0gdGVzdERhdGEuQ09MRF9XQUxMRVRfUk9PVF9BRERSRVNTO1xuICAgICAgbm9jayhgaHR0cHM6Ly9hcGkudGVzdG5ldC5oaXJvLnNvYClcbiAgICAgICAgLmdldChgL2V4dGVuZGVkL3YyL2FkZHJlc3Nlcy8ke3Jvb3RBZGRyZXNzfS9iYWxhbmNlcy9zdHhgKVxuICAgICAgICAucmVwbHkoMjAwLCB0ZXN0RGF0YS5BQ0NPVU5UX0JBTEFOQ0VfUkVTUE9OU0UpO1xuICAgICAgbm9jayhgaHR0cHM6Ly9hcGkudGVzdG5ldC5oaXJvLnNvYClcbiAgICAgICAgLmdldChgL2V4dGVuZGVkL3YxL2FkZHJlc3MvJHtyb290QWRkcmVzc30vbm9uY2VzYClcbiAgICAgICAgLnJlcGx5KDIwMCwgdGVzdERhdGEuQUNDT1VOVF9OT05DRV9SRVNQT05TRSk7XG4gICAgICBub2NrKGBodHRwczovL2FwaS50ZXN0bmV0Lmhpcm8uc29gLCB7IGFsbG93VW5tb2NrZWQ6IHRydWUgfSlcbiAgICAgICAgLnBvc3QoYC92Mi9mZWVzL3RyYW5zYWN0aW9uYCwgdGVzdERhdGEuRkVFX0VTVElNQVRJT05fUkVRVUVTVClcbiAgICAgICAgLnJlcGx5KDIwMCwgdGVzdERhdGEuRkVFX0VTVElNQVRJT05fUkVTUE9OU0UpO1xuXG4gICAgICBjb25zdCByZWNvdmVyeU9wdGlvbnM6IFJlY292ZXJ5T3B0aW9ucyA9IHtcbiAgICAgICAgYmFja3VwS2V5OiB0ZXN0RGF0YS5DT0xEX1dBTExFVF9QVUJMSUNfS0VZX0lORk8uQkFDS1VQX0tFWSxcbiAgICAgICAgdXNlcktleTogdGVzdERhdGEuQ09MRF9XQUxMRVRfUFVCTElDX0tFWV9JTkZPLlVTRVJfS0VZLFxuICAgICAgICByb290QWRkcmVzczogcm9vdEFkZHJlc3MsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHRlc3REYXRhLkRFU1RJTkFUSU9OX0FERFJFU1NfV1JXLFxuICAgICAgICBiaXRnb0tleTogdGVzdERhdGEuQ09MRF9XQUxMRVRfUFVCTElDX0tFWV9JTkZPLkJJVEdPX1BVQl9LRVksXG4gICAgICB9O1xuICAgICAgY29uc3QgcmVzcG9uc2U6IFJlY292ZXJ5SW5mbyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIocmVjb3ZlcnlPcHRpb25zKTtcbiAgICAgIHJlc3BvbnNlLnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eEhleCcpO1xuICAgICAgcmVzcG9uc2Uuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2NvaW4nKTtcbiAgICAgIHJlc3BvbnNlLnNob3VsZC5oYXZlLnByb3BlcnR5KCdmZWVJbmZvJyk7XG4gICAgICBhc3NlcnQuZGVlcEVxdWFsKHJlc3BvbnNlLnR4SGV4LCB0ZXN0RGF0YS5DT0xEX1dBTExFVF9VTlNJR05FRF9TV0VFUF9UWF9IRVgsICd0eCBoZXggbm90IG1hdGNoaW5nIScpO1xuICAgICAgYXNzZXJ0LmRlZXBFcXVhbChyZXNwb25zZS5jb2luLCAndHN0eCcsICdjb2luIG5vdCBtYXRjaGluZyEnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgaW52YWxpZCByb290IGFkZHJlc3Mgd2hlbiByb290IGFkZHJlc3MgaXMgbWlzc2luZyBvciBpbnZhbGlkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVjb3ZlcnlPcHRpb25zOiBSZWNvdmVyeU9wdGlvbnMgPSB7XG4gICAgICAgIGJhY2t1cEtleTogdGVzdERhdGEuQ09MRF9XQUxMRVRfUFVCTElDX0tFWV9JTkZPLkJBQ0tVUF9LRVksXG4gICAgICAgIHVzZXJLZXk6IHRlc3REYXRhLkNPTERfV0FMTEVUX1BVQkxJQ19LRVlfSU5GTy5VU0VSX0tFWSxcbiAgICAgICAgcm9vdEFkZHJlc3M6ICcnLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiB0ZXN0RGF0YS5ERVNUSU5BVElPTl9BRERSRVNTX1dSVyxcbiAgICAgICAgYml0Z29LZXk6IHRlc3REYXRhLkNPTERfV0FMTEVUX1BVQkxJQ19LRVlfSU5GTy5CSVRHT19QVUJfS0VZLFxuICAgICAgfTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIocmVjb3ZlcnlPcHRpb25zKS5zaG91bGQucmVqZWN0ZWRXaXRoKCdpbnZhbGlkIHJvb3QgYWRkcmVzcyEnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgaW52YWxpZCBkZXN0aW5hdGlvbiBhZGRyZXNzIHdoZW4gZGVzdGluYXRpb24gYWRkcmVzcyBpcyBtaXNzaW5nIG9yIGludmFsaWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZWNvdmVyeU9wdGlvbnM6IFJlY292ZXJ5T3B0aW9ucyA9IHtcbiAgICAgICAgYmFja3VwS2V5OiB0ZXN0RGF0YS5DT0xEX1dBTExFVF9QVUJMSUNfS0VZX0lORk8uQkFDS1VQX0tFWSxcbiAgICAgICAgdXNlcktleTogdGVzdERhdGEuQ09MRF9XQUxMRVRfUFVCTElDX0tFWV9JTkZPLlVTRVJfS0VZLFxuICAgICAgICByb290QWRkcmVzczogdGVzdERhdGEuQ09MRF9XQUxMRVRfUk9PVF9BRERSRVNTLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiAnJyxcbiAgICAgICAgYml0Z29LZXk6IHRlc3REYXRhLkNPTERfV0FMTEVUX1BVQkxJQ19LRVlfSU5GTy5CSVRHT19QVUJfS0VZLFxuICAgICAgfTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIocmVjb3ZlcnlPcHRpb25zKS5zaG91bGQucmVqZWN0ZWRXaXRoKCdpbnZhbGlkIGRlc3RpbmF0aW9uIGFkZHJlc3MhJyk7XG4gICAgfSk7XG5cbiAgICBpdChcInNob3VsZCBmYWlsIHdpdGggbm8gYmFsYW5jZSB3aGVuIHJvb3QgYWRkcmVzcyBkb2Vzbid0IGhhdmUgYmFsYW5jZVwiLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByb290QWRkcmVzcyA9IHRlc3REYXRhLkhPVF9XQUxMRVRfUk9PVF9BRERSRVNTO1xuICAgICAgY29uc3Qgc3R4QmFsYW5jZSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGVzdERhdGEuQUNDT1VOVF9CQUxBTkNFX1JFU1BPTlNFKSk7XG4gICAgICBzdHhCYWxhbmNlLmJhbGFuY2UgPSAnMCc7XG4gICAgICBub2NrKGBodHRwczovL2FwaS50ZXN0bmV0Lmhpcm8uc29gKVxuICAgICAgICAuZ2V0KGAvZXh0ZW5kZWQvdjIvYWRkcmVzc2VzLyR7cm9vdEFkZHJlc3N9L2JhbGFuY2VzL3N0eGApXG4gICAgICAgIC5yZXBseSgyMDAsIHN0eEJhbGFuY2UpO1xuICAgICAgbm9jayhgaHR0cHM6Ly9hcGkudGVzdG5ldC5oaXJvLnNvYClcbiAgICAgICAgLmdldChgL2V4dGVuZGVkL3YxL2FkZHJlc3MvJHtyb290QWRkcmVzc30vbm9uY2VzYClcbiAgICAgICAgLnJlcGx5KDIwMCwgdGVzdERhdGEuQUNDT1VOVF9OT05DRV9SRVNQT05TRSk7XG4gICAgICBjb25zdCByZWNvdmVyeU9wdGlvbnM6IFJlY292ZXJ5T3B0aW9ucyA9IHtcbiAgICAgICAgYmFja3VwS2V5OiB0ZXN0RGF0YS5IT1RfV0FMTEVUX0tFWV9DQVJEX0lORk8uQkFDS1VQX0tFWSxcbiAgICAgICAgdXNlcktleTogdGVzdERhdGEuSE9UX1dBTExFVF9LRVlfQ0FSRF9JTkZPLlVTRVJfS0VZLFxuICAgICAgICByb290QWRkcmVzczogcm9vdEFkZHJlc3MsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHRlc3REYXRhLkRFU1RJTkFUSU9OX0FERFJFU1NfV1JXLFxuICAgICAgICBiaXRnb0tleTogdGVzdERhdGEuSE9UX1dBTExFVF9LRVlfQ0FSRF9JTkZPLkJJVEdPX1BVQl9LRVksXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHRlc3REYXRhLkhPVF9XQUxMRVRfS0VZX0NBUkRfSU5GTy5XQUxMRVRfUEFTU1BIUkFTRSxcbiAgICAgIH07XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAucmVjb3ZlcihyZWNvdmVyeU9wdGlvbnMpXG4gICAgICAgIC5zaG91bGQucmVqZWN0ZWRXaXRoKGBjb3VsZCBub3QgZmluZCBhbnkgYmFsYW5jZSB0byByZWNvdmVyIGZvciAke3Jvb3RBZGRyZXNzfWApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHdpdGggaW5zdWZmaWNpZW50IGJhbGFuY2Ugd2hlbiBzdHggYmFsYW5jZSBpcyBsb3dlciB0aGFuIGZlZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJvb3RBZGRyZXNzID0gdGVzdERhdGEuSE9UX1dBTExFVF9ST09UX0FERFJFU1M7XG4gICAgICAvLyBkZWVwIGNsb25lIHRvIHN0b3AgbXV0YXRpb25cbiAgICAgIGNvbnN0IGFjY291bnRCYWxhbmNlID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0ZXN0RGF0YS5BQ0NPVU5UX0JBTEFOQ0VfUkVTUE9OU0UpKTtcbiAgICAgIGFjY291bnRCYWxhbmNlLmJhbGFuY2UgPSAnMTAwJzsgLy8gc2V0IGJhbGFuY2UgbG93ZXIgdGhhbiBmZWVcbiAgICAgIG5vY2soYGh0dHBzOi8vYXBpLnRlc3RuZXQuaGlyby5zb2ApXG4gICAgICAgIC5nZXQoYC9leHRlbmRlZC92Mi9hZGRyZXNzZXMvJHtyb290QWRkcmVzc30vYmFsYW5jZXMvc3R4YClcbiAgICAgICAgLnJlcGx5KDIwMCwgYWNjb3VudEJhbGFuY2UpO1xuICAgICAgbm9jayhgaHR0cHM6Ly9hcGkudGVzdG5ldC5oaXJvLnNvYClcbiAgICAgICAgLmdldChgL2V4dGVuZGVkL3YxL2FkZHJlc3MvJHtyb290QWRkcmVzc30vbm9uY2VzYClcbiAgICAgICAgLnJlcGx5KDIwMCwgdGVzdERhdGEuQUNDT1VOVF9OT05DRV9SRVNQT05TRSk7XG4gICAgICBjb25zdCBmZWVSZXF1ZXN0Qm9keSA9IHRlc3REYXRhLkZFRV9FU1RJTUFUSU9OX1JFUVVFU1Q7XG4gICAgICBmZWVSZXF1ZXN0Qm9keS50cmFuc2FjdGlvbl9wYXlsb2FkID1cbiAgICAgICAgJzAwMDUxYTE1MDBhMWM0MmYwYzExYmZlMzg5M2Y0NzlhZjE4OTA0Njc3Njg1YmUwMDAwMDAwMDAwMDAwMDY0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAnO1xuICAgICAgbm9jayhgaHR0cHM6Ly9hcGkudGVzdG5ldC5oaXJvLnNvYCwgeyBhbGxvd1VubW9ja2VkOiB0cnVlIH0pXG4gICAgICAgIC5wb3N0KGAvdjIvZmVlcy90cmFuc2FjdGlvbmAsIGZlZVJlcXVlc3RCb2R5KVxuICAgICAgICAucmVwbHkoMjAwLCB0ZXN0RGF0YS5GRUVfRVNUSU1BVElPTl9SRVNQT05TRSk7XG4gICAgICBjb25zdCByZWNvdmVyeU9wdGlvbnM6IFJlY292ZXJ5T3B0aW9ucyA9IHtcbiAgICAgICAgYmFja3VwS2V5OiB0ZXN0RGF0YS5IT1RfV0FMTEVUX0tFWV9DQVJEX0lORk8uQkFDS1VQX0tFWSxcbiAgICAgICAgdXNlcktleTogdGVzdERhdGEuSE9UX1dBTExFVF9LRVlfQ0FSRF9JTkZPLlVTRVJfS0VZLFxuICAgICAgICByb290QWRkcmVzczogcm9vdEFkZHJlc3MsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHRlc3REYXRhLkRFU1RJTkFUSU9OX0FERFJFU1NfV1JXLFxuICAgICAgICBiaXRnb0tleTogdGVzdERhdGEuSE9UX1dBTExFVF9LRVlfQ0FSRF9JTkZPLkJJVEdPX1BVQl9LRVksXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHRlc3REYXRhLkhPVF9XQUxMRVRfS0VZX0NBUkRfSU5GTy5XQUxMRVRfUEFTU1BIUkFTRSxcbiAgICAgIH07XG4gICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHJlY292ZXJ5T3B0aW9ucykuc2hvdWxkLnJlamVjdGVkV2l0aCgnaW5zdWZmaWNpZW50IGJhbGFuY2UgdG8gYnVpbGQgdGhlIHRyYW5zYWN0aW9uJyk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=Выполнить команду
Для локальной разработки. Не используйте в интернете!