PHP WebShell

Текущая директория: /opt/BitGoJS/modules/bitgo/dist/test/v2/unit/lightning

Просмотр файла: lightningWallets.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assert = require("assert");
const sdk_test_1 = require("@bitgo/sdk-test");
const nock = require("nock");
const sdk_core_1 = require("@bitgo/sdk-core");
const abstract_lightning_1 = require("@bitgo/abstract-lightning");
const src_1 = require("../../../../src");
describe('Lightning wallets', function () {
    const coinName = 'tlnbtc';
    const bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
    let basecoin;
    let wallets;
    let bgUrl;
    const userAuthKey = {
        id: 'def',
        pub: 'xpub661MyMwAqRbcGYjYsnsDj1SHdiXynWEXNnfNgMSpokN54FKyMqbu7rWEfVNDs6uAJmz86UVFtq4sefhQpXZhSAzQcL9zrEPtiLNNZoeSxCG',
        encryptedPrv: '{"iv":"zYhhaNdW0wPfJEoBjZ4pvg==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"tgAMua9jjhw=","ct":"HcrbxQvNlWG5tLMndYzdNCYa1l+1h7o+vSsweA0+q1le3tWt6jLUJSEjZN+JI8lTZ2KPFQgLulQQhsUa+ytUCBi0vSgjF7x7CprT7l2Cfjkew00XsEd7wnmtJUsrQk8m69Co7tIRA3oEgzrnYwy4qOM81lbNNyQ="}',
        source: 'user',
        coinSpecific: {
            tlnbtc: {
                purpose: 'userAuth',
            },
        },
    };
    const nodeAuthKey = {
        id: 'ghi',
        pub: 'xpub661MyMwAqRbcG9xnTnAnRbJPo3MAHyRtH4zeehN8exYk4VFz5buepUzebhix33BKhS5Eb4V3LEfW5pYiSR8qmaEnyrpeghhKY8JfzAsUDpq',
        encryptedPrv: '{"iv":"bH6eGbnl9x8PZECPrgvcng==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"o8yknV6nTI8=","ct":"nGyzAToIzYkQeIdcVafoWHtMx7+Fgj0YldCme3WA1yxJAA0QulZVhblMZN/7efCRIumA0NNmpH7dxH6n8cVlz/Z+RUgC2q9lgvZKUoJcYNTjWUfkmkJutXX2tr8yVxm+eC/hnRiyfVLZ2qPxctvDlBVBfgLuPyc="}',
        source: 'user',
        coinSpecific: {
            tlnbtc: {
                purpose: 'nodeAuth',
            },
        },
    };
    before(function () {
        bitgo.initializeTestVars();
        basecoin = bitgo.coin(coinName);
        wallets = basecoin.wallets();
        bgUrl = src_1.common.Environments[bitgo.getEnv()].uri;
    });
    after(function () {
        nock.cleanAll();
        nock.pendingMocks().length.should.equal(0);
    });
    describe('Generate lightning wallet', function () {
        it('should validate parameters', async function () {
            await wallets
                .generateWallet({
                passphrase: 'pass123',
                enterprise: 'ent123',
                passcodeEncryptionCode: 'code123',
                subType: 'lightningCustody',
            })
                .should.be.rejectedWith("error(s) parsing generate lightning wallet request params: Invalid value 'undefined' supplied to GenerateLightningWalletOptions.label, expected string.");
            await wallets
                .generateWallet({
                label: 'my ln wallet',
                enterprise: 'ent123',
                passcodeEncryptionCode: 'code123',
                subType: 'lightningCustody',
            })
                .should.be.rejectedWith("error(s) parsing generate lightning wallet request params: Invalid value 'undefined' supplied to GenerateLightningWalletOptions.passphrase, expected string.");
            await wallets
                .generateWallet({
                label: 'my ln wallet',
                passphrase: 'pass123',
                passcodeEncryptionCode: 'code123',
                subType: 'lightningCustody',
            })
                .should.be.rejectedWith("error(s) parsing generate lightning wallet request params: Invalid value 'undefined' supplied to GenerateLightningWalletOptions.enterprise, expected string.");
            await wallets
                .generateWallet({
                label: 'my ln wallet',
                passphrase: 'pass123',
                enterprise: 'ent123',
                subType: 'lightningCustody',
            })
                .should.be.rejectedWith("error(s) parsing generate lightning wallet request params: Invalid value 'undefined' supplied to GenerateLightningWalletOptions.passcodeEncryptionCode, expected string.");
            await wallets
                .generateWallet({
                label: 123,
                passphrase: 'pass123',
                enterprise: 'ent123',
                passcodeEncryptionCode: 'code123',
                subType: 'lightningCustody',
            })
                .should.be.rejectedWith("error(s) parsing generate lightning wallet request params: Invalid value '123' supplied to GenerateLightningWalletOptions.label, expected string.");
            await wallets
                .generateWallet({
                label: 'my ln wallet',
                passphrase: 123,
                enterprise: 'ent123',
                passcodeEncryptionCode: 'code123',
                subType: 'lightningCustody',
            })
                .should.be.rejectedWith("error(s) parsing generate lightning wallet request params: Invalid value '123' supplied to GenerateLightningWalletOptions.passphrase, expected string.");
            await wallets
                .generateWallet({
                label: 'my ln wallet',
                passphrase: 'pass123',
                enterprise: 123,
                passcodeEncryptionCode: 'code123',
                subType: 'lightningCustody',
            })
                .should.be.rejectedWith("error(s) parsing generate lightning wallet request params: Invalid value '123' supplied to GenerateLightningWalletOptions.enterprise, expected string.");
            await wallets
                .generateWallet({
                label: 'my ln wallet',
                passphrase: 'pass123',
                enterprise: 'ent123',
                passcodeEncryptionCode: 123,
                subType: 'lightningCustody',
            })
                .should.be.rejectedWith("error(s) parsing generate lightning wallet request params: Invalid value '123' supplied to GenerateLightningWalletOptions.passcodeEncryptionCode, expected string.");
        });
        for (const subType of ['lightningCustody', 'lightningSelfCustody']) {
            it(`should generate ${subType} lightning wallet`, async function () {
                const params = {
                    label: 'my ln wallet',
                    passphrase: 'pass123',
                    enterprise: 'ent123',
                    passcodeEncryptionCode: 'code123',
                    subType: subType,
                };
                const validateKeyRequest = (body) => {
                    const baseChecks = body.pub.startsWith('xpub') &&
                        !!body.encryptedPrv &&
                        body.keyType === 'independent' &&
                        body.source === 'user';
                    if (body.originalPasscodeEncryptionCode !== undefined) {
                        return baseChecks && body.originalPasscodeEncryptionCode === 'code123' && body.coinSpecific === undefined;
                    }
                    else {
                        const coinSpecific = body.coinSpecific && body.coinSpecific.tlnbtc;
                        return baseChecks && !!coinSpecific && ['userAuth', 'nodeAuth'].includes(coinSpecific.purpose);
                    }
                };
                const validateWalletRequest = (body) => {
                    return (body.label === 'my ln wallet' &&
                        body.m === 1 &&
                        body.n === 1 &&
                        body.type === 'hot' &&
                        body.subType === subType &&
                        body.enterprise === 'ent123' &&
                        Array.isArray(body.keys) &&
                        body.keys.length === 1 &&
                        body.keys[0] === 'keyId1' &&
                        body.coinSpecific &&
                        body.coinSpecific.tlnbtc &&
                        Array.isArray(body.coinSpecific.tlnbtc.keys) &&
                        body.coinSpecific.tlnbtc.keys.length === 2 &&
                        body.coinSpecific.tlnbtc.keys.includes('keyId2') &&
                        body.coinSpecific.tlnbtc.keys.includes('keyId3'));
                };
                nock(bgUrl)
                    .post('/api/v2/' + coinName + '/key', (body) => validateKeyRequest(body))
                    .reply(200, { id: 'keyId1' });
                nock(bgUrl)
                    .post('/api/v2/' + coinName + '/key', (body) => validateKeyRequest(body))
                    .reply(200, { id: 'keyId2' });
                nock(bgUrl)
                    .post('/api/v2/' + coinName + '/key', (body) => validateKeyRequest(body))
                    .reply(200, { id: 'keyId3' });
                nock(bgUrl)
                    .post('/api/v2/' + coinName + '/wallet/add', (body) => validateWalletRequest(body))
                    .reply(200, { id: 'walletId' });
                const response = await wallets.generateWallet(params);
                assert.ok(response.wallet);
                assert.ok(response.encryptedWalletPassphrase);
                assert.equal(bitgo.decrypt({ input: response.encryptedWalletPassphrase, password: params.passcodeEncryptionCode }), params.passphrase);
            });
        }
    });
    describe('invoices', function () {
        let wallet;
        beforeEach(function () {
            wallet = (0, abstract_lightning_1.getLightningWallet)(new src_1.Wallet(bitgo, basecoin, {
                id: 'walletId',
                coin: 'tlnbtc',
                subType: 'lightningCustody',
                coinSpecific: { keys: ['def', 'ghi'] },
            }));
        });
        it('should list invoices', async function () {
            const invoice = {
                valueMsat: 1000n,
                paymentHash: 'foo',
                invoice: 'tlnfoobar',
                walletId: wallet.wallet.id(),
                status: 'open',
                expiresAt: new Date(),
                createdAt: new Date(),
                updatedAt: new Date(),
            };
            const query = {
                status: 'open',
                startDate: new Date(),
                limit: 100n,
            };
            const listInvoicesNock = nock(bgUrl)
                .get(`/api/v2/wallet/${wallet.wallet.id()}/lightning/invoice`)
                .query(abstract_lightning_1.InvoiceQuery.encode(query))
                .reply(200, [abstract_lightning_1.InvoiceInfo.encode(invoice)]);
            const invoiceResponse = await wallet.listInvoices(query);
            assert.strictEqual(invoiceResponse.length, 1);
            assert.deepStrictEqual(invoiceResponse[0], invoice);
            listInvoicesNock.done();
        });
        it('listInvoices should throw error if wp response is invalid', async function () {
            const listInvoicesNock = nock(bgUrl)
                .get(`/api/v2/wallet/${wallet.wallet.id()}/lightning/invoice`)
                .reply(200, [{ valueMsat: '1000' }]);
            await assert.rejects(async () => await wallet.listInvoices({}), /Invalid list invoices response/);
            listInvoicesNock.done();
        });
        it('should create invoice', async function () {
            const createInvoice = {
                valueMsat: 1000n,
                memo: 'test invoice',
                expiry: 100,
            };
            const invoice = {
                invoice: 'tlnabc',
                paymentHash: '123',
                expiresAt: new Date(),
                status: 'open',
                walletId: wallet.wallet.id(),
                valueMsat: 1000n,
            };
            const createInvoiceNock = nock(bgUrl)
                .post(`/api/v2/wallet/${wallet.wallet.id()}/lightning/invoice`, abstract_lightning_1.CreateInvoiceBody.encode(createInvoice))
                .reply(200, abstract_lightning_1.Invoice.encode(invoice));
            const createInvoiceResponse = await wallet.createInvoice(createInvoice);
            assert.deepStrictEqual(createInvoiceResponse, invoice);
            createInvoiceNock.done();
        });
        it('createInvoice should throw error if wp response is invalid', async function () {
            const createInvoice = {
                valueMsat: 1000n,
                memo: 'test invoice',
                expiry: 100,
            };
            const createInvoiceNock = nock(bgUrl)
                .post(`/api/v2/wallet/${wallet.wallet.id()}/lightning/invoice`)
                .reply(200, { valueMsat: '1000' });
            await assert.rejects(async () => await wallet.createInvoice(createInvoice), /Invalid create invoice response/);
            createInvoiceNock.done();
        });
        it('should pay invoice', async function () {
            const params = {
                invoice: 'lnbc1...',
                amountMsat: 1000n,
                feeLimitMsat: 100n,
                feeLimitRatio: 0.1,
                sequenceId: '123',
                comment: 'test payment',
                passphrase: 'password123',
            };
            const txRequestResponse = {
                txRequestId: 'txReq123',
                state: 'delivered',
            };
            const lndResponse = {
                status: 'settled',
                paymentHash: 'paymentHash123',
                amountMsat: params.amountMsat !== undefined ? params.amountMsat.toString() : undefined,
                feeMsat: params.feeLimitMsat !== undefined ? params.feeLimitMsat.toString() : undefined,
                paymentPreimage: 'preimage123',
            };
            const finalPaymentResponse = {
                txRequestId: 'txReq123',
                state: 'delivered',
                transactions: [
                    {
                        unsignedTx: {
                            coinSpecific: {
                                ...lndResponse,
                            },
                        },
                    },
                ],
            };
            const transferData = {
                id: 'fake_id',
                coin: 'tlnbtc',
                state: 'confirmed',
                txid: lndResponse.paymentHash,
            };
            const getTransferNock = nock(bgUrl)
                .get(`/api/v2/${coinName}/wallet/${wallet.wallet.id()}/transfer/${lndResponse.paymentHash}`)
                .reply(200, transferData);
            const createTxRequestNock = nock(bgUrl)
                .post(`/api/v2/wallet/${wallet.wallet.id()}/txrequests`)
                .reply(200, txRequestResponse);
            const sendTxRequestNock = nock(bgUrl)
                .post(`/api/v2/wallet/${wallet.wallet.id()}/txrequests/${txRequestResponse.txRequestId}/transactions/0/send`)
                .reply(200, finalPaymentResponse);
            const userAuthKeyNock = nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/def')
                .reply(200, userAuthKey);
            const nodeAuthKeyNock = nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/ghi')
                .reply(200, nodeAuthKey);
            const response = await wallet.payInvoice(params);
            assert.strictEqual(response.txRequestId, 'txReq123');
            assert.strictEqual(response.txRequestState, 'delivered');
            assert(response.paymentStatus);
            assert.strictEqual(response.paymentStatus.status, finalPaymentResponse.transactions[0].unsignedTx.coinSpecific.status);
            assert.strictEqual(response.paymentStatus.paymentHash, finalPaymentResponse.transactions[0].unsignedTx.coinSpecific.paymentHash);
            assert.strictEqual(response.paymentStatus.amountMsat, finalPaymentResponse.transactions[0].unsignedTx.coinSpecific.amountMsat);
            assert.strictEqual(response.paymentStatus.feeMsat, finalPaymentResponse.transactions[0].unsignedTx.coinSpecific.feeMsat);
            assert.strictEqual(response.paymentStatus.paymentPreimage, finalPaymentResponse.transactions[0].unsignedTx.coinSpecific.paymentPreimage);
            getTransferNock.done();
            createTxRequestNock.done();
            sendTxRequestNock.done();
            userAuthKeyNock.done();
            nodeAuthKeyNock.done();
        });
        it('should handle pending approval when paying invoice', async function () {
            const params = {
                invoice: 'lnbc1...',
                amountMsat: 1000n,
                feeLimitMsat: 100n,
                feeLimitRatio: 0.1,
                sequenceId: '123',
                comment: 'test payment',
                passphrase: 'password123',
            };
            const txRequestResponse = {
                txRequestId: 'txReq123',
                state: 'pendingApproval',
                pendingApprovalId: 'approval123',
            };
            const pendingApprovalData = {
                id: 'approval123',
                state: sdk_core_1.State.PENDING,
                creator: 'user123',
                info: {
                    type: sdk_core_1.Type.TRANSACTION_REQUEST,
                },
            };
            const createTxRequestNock = nock(bgUrl)
                .post(`/api/v2/wallet/${wallet.wallet.id()}/txrequests`)
                .reply(200, txRequestResponse);
            const getPendingApprovalNock = nock(bgUrl)
                .get(`/api/v2/${coinName}/pendingapprovals/${txRequestResponse.pendingApprovalId}`)
                .reply(200, pendingApprovalData);
            const userAuthKeyNock = nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/def')
                .reply(200, userAuthKey);
            const nodeAuthKeyNock = nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/ghi')
                .reply(200, nodeAuthKey);
            const response = await wallet.payInvoice(params);
            assert.strictEqual(response.txRequestId, 'txReq123');
            assert.strictEqual(response.txRequestState, 'pendingApproval');
            assert(response.pendingApproval);
            assert.strictEqual(response.paymentStatus, undefined);
            createTxRequestNock.done();
            getPendingApprovalNock.done();
            userAuthKeyNock.done();
            nodeAuthKeyNock.done();
        });
    });
    describe('Get lightning key(s)', function () {
        const walletData = {
            id: 'fakeid',
            coin: coinName,
            keys: ['abc'],
            coinSpecific: { keys: ['def', 'ghi'] },
            subType: 'lightningCustody',
        };
        const userKeyData = {
            id: 'abc',
            pub: 'xpub1',
            encryptedPrv: 'encryptedPrv1',
            source: 'user',
        };
        const userAuthKeyData = {
            id: 'def',
            pub: 'xpub2',
            encryptedPrv: 'encryptedPrv2',
            source: 'user',
            coinSpecific: {
                tlnbtc: {
                    purpose: 'userAuth',
                },
            },
        };
        const nodeAuthKeyData = {
            id: 'ghi',
            pub: 'xpub3',
            encryptedPrv: 'encryptedPrv3',
            source: 'user',
            coinSpecific: {
                tlnbtc: {
                    purpose: 'nodeAuth',
                },
            },
        };
        it('should get lightning key', async function () {
            const wallet = new src_1.Wallet(bitgo, basecoin, walletData);
            const keyNock = nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/abc')
                .reply(200, userKeyData);
            const key = await (0, abstract_lightning_1.getLightningKeychain)(wallet);
            assert.deepStrictEqual(key, userKeyData);
            keyNock.done();
        });
        it('should get lightning auth keys', async function () {
            const wallet = new src_1.Wallet(bitgo, basecoin, walletData);
            const userAuthKeyNock = nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/def')
                .reply(200, userAuthKeyData);
            const nodeAuthKeyNock = nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/ghi')
                .reply(200, nodeAuthKeyData);
            const { userAuthKey, nodeAuthKey } = await (0, abstract_lightning_1.getLightningAuthKeychains)(wallet);
            assert.deepStrictEqual(userAuthKey, userAuthKeyData);
            assert.deepStrictEqual(nodeAuthKey, nodeAuthKeyData);
            userAuthKeyNock.done();
            nodeAuthKeyNock.done();
        });
        it('should fail to get lightning key for invalid number of keys', async function () {
            const wallet = new src_1.Wallet(bitgo, basecoin, { ...walletData, keys: [] });
            await assert.rejects(async () => await (0, abstract_lightning_1.getLightningKeychain)(wallet), /Error: Invalid number of key in lightning wallet: 0/);
        });
        it('should fail to get lightning auth keys for invalid number of keys', async function () {
            const wallet = new src_1.Wallet(bitgo, basecoin, { ...walletData, coinSpecific: { keys: ['def'] } });
            await assert.rejects(async () => await (0, abstract_lightning_1.getLightningAuthKeychains)(wallet), /Error: Invalid number of auth keys in lightning wallet: 1/);
        });
        it('should fail to get lightning key for invalid response', async function () {
            const wallet = new src_1.Wallet(bitgo, basecoin, walletData);
            nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/abc')
                .reply(200, { ...userKeyData, source: 'backup' });
            await assert.rejects(async () => await (0, abstract_lightning_1.getLightningKeychain)(wallet), /Error: Invalid user key/);
        });
        it('should fail to get lightning auth keys for invalid response', async function () {
            const wallet = new src_1.Wallet(bitgo, basecoin, walletData);
            nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/def')
                .reply(200, { ...userAuthKeyData, source: 'backup' });
            nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/ghi')
                .reply(200, nodeAuthKeyData);
            await assert.rejects(async () => await (0, abstract_lightning_1.getLightningAuthKeychains)(wallet), /Error: Invalid lightning auth key: def/);
        });
    });
    describe('Update lightning wallet coin specific', function () {
        const walletData = {
            id: 'fakeid',
            coin: coinName,
            keys: ['abc'],
            coinSpecific: { keys: ['def', 'ghi'] },
            subType: 'lightningSelfCustody',
        };
        const watchOnlyAccounts = {
            master_key_birthday_timestamp: 'dummy',
            master_key_fingerprint: 'dummy',
            accounts: [
                {
                    xpub: 'upub5Eep7H5q39PzQZLVEYLBytDyBNeV74E8mQsyeL6UozFq9Y3MsZ52G7YGuqrJPgoyAqF7TBeJdnkrHrVrB5pkWkPJ9cJGAePMU6F1Gyw6aFH',
                    purpose: 49,
                    coin_type: 0,
                    account: 0,
                },
                {
                    xpub: 'vpub5ZU1PHGpQoDSHckYico4nsvwsD3mTh6UjqL5zyGWXZXzBjTYMNKot7t9eRPQY71hJcnNN9r1ss25g3xA9rmoJ5nWPg8jEWavrttnsVa1qw1',
                    purpose: 84,
                    coin_type: 0,
                    account: 0,
                },
            ],
        };
        it('should update wallet', async function () {
            const wallet = new src_1.Wallet(bitgo, basecoin, walletData);
            const userAuthKeyNock = nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/def')
                .reply(200, userAuthKey);
            const nodeAuthKeyNock = nock(bgUrl)
                .get('/api/v2/' + coinName + '/key/ghi')
                .reply(200, nodeAuthKey);
            let capturedBody;
            const wpWalletUpdateNock = nock(bgUrl)
                .put(`/api/v2/tlnbtc/wallet/${walletData.id}`)
                .reply(function (uri, requestBody) {
                capturedBody = requestBody;
                return [200];
            });
            const params = {
                signerMacaroon: 'signerMacaroon',
                signerAdminMacaroon: 'signerAdminMacaroon',
                signerTlsKey: 'signerTlsKey',
                signerTlsCert: 'signerTlsCert',
                watchOnlyAccounts,
                passphrase: 'password123',
            };
            await assert.doesNotReject(async () => await (0, abstract_lightning_1.updateWalletCoinSpecific)(wallet, params));
            assert(userAuthKeyNock.isDone());
            assert(nodeAuthKeyNock.isDone());
            assert(wpWalletUpdateNock.isDone());
            // Verify structure and required fields
            assert.ok(capturedBody.coinSpecific?.tlnbtc?.signedRequest, 'signedRequest should exist');
            const signedRequest = capturedBody.coinSpecific.tlnbtc.signedRequest;
            assert.ok(signedRequest.signerTlsCert, 'signerTlsCert should exist');
            assert.ok(signedRequest.watchOnlyAccounts, 'watchOnlyAccounts should exist');
            assert.ok(signedRequest.encryptedSignerTlsKey, 'encryptedSignerTlsKey should exist');
            assert.ok(signedRequest.encryptedSignerAdminMacaroon, 'encryptedSignerAdminMacaroon should exist');
            assert.ok(signedRequest.encryptedSignerMacaroon, 'encryptedSignerMacaroon should exist');
            // Verify signature exists
            assert.ok(capturedBody.coinSpecific.tlnbtc.signature, 'signature should exist');
            // we should not pass passphrase to the backend
            assert.strictEqual(signedRequest.passphrase, undefined, 'passphrase should not exist in request');
        });
    });
    describe('On chain withdrawal', function () {
        let wallet;
        beforeEach(function () {
            wallet = (0, abstract_lightning_1.getLightningWallet)(new src_1.Wallet(bitgo, basecoin, {
                id: 'walletId',
                coin: 'tlnbtc',
                subType: 'lightningCustody',
                coinSpecific: { keys: ['def', 'ghi'] },
            }));
        });
        it('should withdraw on chain', async function () {
            const params = {
                recipients: [
                    {
                        amountSat: 500000n,
                        address: 'bcrt1qjq48cqk2u80hewdcndf539m8nnnvt845nl68x7',
                    },
                ],
                satsPerVbyte: 15n,
            };
            const txRequestResponse = {
                txRequestId: 'txReq123',
                state: 'pendingDelivery',
            };
            const finalPaymentResponse = {
                txRequestId: 'txReq123',
                state: 'delivered',
            };
            const createTxRequestNock = nock(bgUrl)
                .post(`/api/v2/wallet/${wallet.wallet.id()}/txrequests`)
                .reply(200, txRequestResponse);
            const sendTxRequestNock = nock(bgUrl)
                .post(`/api/v2/wallet/${wallet.wallet.id()}/txrequests/${txRequestResponse.txRequestId}/transactions/0/send`)
                .reply(200, finalPaymentResponse);
            const response = await wallet.withdrawOnchain(params);
            assert.strictEqual(response.txRequestId, 'txReq123');
            assert.strictEqual(response.txRequestState, 'delivered');
            createTxRequestNock.done();
            sendTxRequestNock.done();
        });
        it('should handle pending approval when withdrawing onchain', async function () {
            const params = {
                recipients: [
                    {
                        amountSat: 500000n,
                        address: 'bcrt1qjq48cqk2u80hewdcndf539m8nnnvt845nl68x7',
                    },
                ],
                satsPerVbyte: 15n,
            };
            const txRequestResponse = {
                txRequestId: 'txReq123',
                state: 'pendingApproval',
                pendingApprovalId: 'approval123',
            };
            const pendingApprovalData = {
                id: 'approval123',
                state: sdk_core_1.State.PENDING,
                creator: 'user123',
                info: {
                    type: sdk_core_1.Type.TRANSACTION_REQUEST,
                },
            };
            const createTxRequestNock = nock(bgUrl)
                .post(`/api/v2/wallet/${wallet.wallet.id()}/txrequests`)
                .reply(200, txRequestResponse);
            const getPendingApprovalNock = nock(bgUrl)
                .get(`/api/v2/${coinName}/pendingapprovals/${txRequestResponse.pendingApprovalId}`)
                .reply(200, pendingApprovalData);
            const response = await wallet.withdrawOnchain(params);
            assert.strictEqual(response.txRequestId, 'txReq123');
            assert.strictEqual(response.txRequestState, 'pendingApproval');
            assert(response.pendingApproval);
            createTxRequestNock.done();
            getPendingApprovalNock.done();
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRuaW5nV2FsbGV0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Rlc3QvdjIvdW5pdC9saWdodG5pbmcvbGlnaHRuaW5nV2FsbGV0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGlDQUFpQztBQUNqQyw4Q0FBNEM7QUFDNUMsNkJBQTZCO0FBQzdCLDhDQUE2RTtBQUM3RSxrRUFjbUM7QUFFbkMseUNBQWlHO0FBRWpHLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRTtJQUM1QixNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDMUIsTUFBTSxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsV0FBSyxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDekQsSUFBSSxRQUFrQixDQUFDO0lBQ3ZCLElBQUksT0FBZ0IsQ0FBQztJQUNyQixJQUFJLEtBQWEsQ0FBQztJQUVsQixNQUFNLFdBQVcsR0FBRztRQUNsQixFQUFFLEVBQUUsS0FBSztRQUNULEdBQUcsRUFBRSxpSEFBaUg7UUFDdEgsWUFBWSxFQUNWLDRTQUE0UztRQUM5UyxNQUFNLEVBQUUsTUFBTTtRQUNkLFlBQVksRUFBRTtZQUNaLE1BQU0sRUFBRTtnQkFDTixPQUFPLEVBQUUsVUFBVTthQUNwQjtTQUNGO0tBQ0YsQ0FBQztJQUVGLE1BQU0sV0FBVyxHQUFHO1FBQ2xCLEVBQUUsRUFBRSxLQUFLO1FBQ1QsR0FBRyxFQUFFLGlIQUFpSDtRQUN0SCxZQUFZLEVBQ1YsNFNBQTRTO1FBQzlTLE1BQU0sRUFBRSxNQUFNO1FBQ2QsWUFBWSxFQUFFO1lBQ1osTUFBTSxFQUFFO2dCQUNOLE9BQU8sRUFBRSxVQUFVO2FBQ3BCO1NBQ0Y7S0FDRixDQUFDO0lBRUYsTUFBTSxDQUFDO1FBQ0wsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFFM0IsUUFBUSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7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QUFNLFFBQVEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBQ3JELE1BQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLGNBQWMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQy9ELE1BQU0sQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUM7WUFFakMsbUJBQW1CLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDM0Isc0JBQXNCLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDaEMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgeyBUZXN0Qml0R28gfSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuaW1wb3J0ICogYXMgbm9jayBmcm9tICdub2NrJztcbmltcG9ydCB7IEJhc2VDb2luLCBQZW5kaW5nQXBwcm92YWxEYXRhLCBTdGF0ZSwgVHlwZSB9IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQge1xuICBDcmVhdGVJbnZvaWNlQm9keSxcbiAgZ2V0TGlnaHRuaW5nV2FsbGV0LFxuICBJbnZvaWNlLFxuICBJbnZvaWNlSW5mbyxcbiAgSW52b2ljZVF1ZXJ5LFxuICBMbmRDcmVhdGVQYXltZW50UmVzcG9uc2UsXG4gIExpZ2h0bmluZ1dhbGxldCxcbiAgU3VibWl0UGF5bWVudFBhcmFtcyxcbiAgVXBkYXRlTGlnaHRuaW5nV2FsbGV0Q2xpZW50UmVxdWVzdCxcbiAgZ2V0TGlnaHRuaW5nS2V5Y2hhaW4sXG4gIGdldExpZ2h0bmluZ0F1dGhLZXljaGFpbnMsXG4gIHVwZGF0ZVdhbGxldENvaW5TcGVjaWZpYyxcbiAgTGlnaHRuaW5nT25jaGFpbldpdGhkcmF3UGFyYW1zLFxufSBmcm9tICdAYml0Z28vYWJzdHJhY3QtbGlnaHRuaW5nJztcblxuaW1wb3J0IHsgQml0R28sIGNvbW1vbiwgR2VuZXJhdGVMaWdodG5pbmdXYWxsZXRPcHRpb25zLCBXYWxsZXQsIFdhbGxldHMgfSBmcm9tICcuLi8uLi8uLi8uLi9zcmMnO1xuXG5kZXNjcmliZSgnTGlnaHRuaW5nIHdhbGxldHMnLCBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IGNvaW5OYW1lID0gJ3RsbmJ0Yyc7XG4gIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICBsZXQgYmFzZWNvaW46IEJhc2VDb2luO1xuICBsZXQgd2FsbGV0czogV2FsbGV0cztcbiAgbGV0IGJnVXJsOiBzdHJpbmc7XG5cbiAgY29uc3QgdXNlckF1dGhLZXkgPSB7XG4gICAgaWQ6ICdkZWYnLFxuICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNHWWpZc25zRGoxU0hkaVh5bldFWE5uZk5nTVNwb2tONTRGS3lNcWJ1N3JXRWZWTkRzNnVBSm16ODZVVkZ0cTRzZWZoUXBYWmhTQXpRY0w5enJFUHRpTE5OWm9lU3hDRycsXG4gICAgZW5jcnlwdGVkUHJ2OlxuICAgICAgJ3tcIml2XCI6XCJ6WWhoYU5kVzB3UGZKRW9Calo0cHZnPT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAwLFwia3NcIjoyNTYsXCJ0c1wiOjY0LFwibW9kZVwiOlwiY2NtXCIsXCJhZGF0YVwiOlwiXCIsXCJjaXBoZXJcIjpcImFlc1wiLFwic2FsdFwiOlwidGdBTXVhOWpqaHc9XCIsXCJjdFwiOlwiSGNyYnhRdk5sV0c1dExNbmRZemROQ1lhMWwrMWg3byt2U3N3ZUEwK3ExbGUzdFd0NmpMVUpTRWpaTitKSThsVFoyS1BGUWdMdWxRUWhzVWEreXRVQ0JpMHZTZ2pGN3g3Q3ByVDdsMkNmamtldzAwWHNFZDd3bm10SlVzclFrOG02OUNvN3RJUkEzb0VnenJuWXd5NHFPTTgxbGJOTnlRPVwifScsXG4gICAgc291cmNlOiAndXNlcicsXG4gICAgY29pblNwZWNpZmljOiB7XG4gICAgICB0bG5idGM6IHtcbiAgICAgICAgcHVycG9zZTogJ3VzZXJBdXRoJyxcbiAgICAgIH0sXG4gICAgfSxcbiAgfTtcblxuICBjb25zdCBub2RlQXV0aEtleSA9IHtcbiAgICBpZDogJ2doaScsXG4gICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0c5eG5UbkFuUmJKUG8zTUFIeVJ0SDR6ZWVoTjhleFlrNFZGejVidWVwVXplYmhpeDMzQktoUzVFYjRWM0xFZlc1cFlpU1I4cW1hRW55cnBlZ2hoS1k4SmZ6QXNVRHBxJyxcbiAgICBlbmNyeXB0ZWRQcnY6XG4gICAgICAne1wiaXZcIjpcImJINmVHYm5sOXg4UFpFQ1ByZ3Zjbmc9PVwiLFwidlwiOjEsXCJpdGVyXCI6MTAwMDAsXCJrc1wiOjI1NixcInRzXCI6NjQsXCJtb2RlXCI6XCJjY21cIixcImFkYXRhXCI6XCJcIixcImNpcGhlclwiOlwiYWVzXCIsXCJzYWx0XCI6XCJvOHlrblY2blRJOD1cIixcImN0XCI6XCJuR3l6QVRvSXpZa1FlSWRjVmFmb1dIdE14NytGZ2owWWxkQ21lM1dBMXl4SkFBMFF1bFpWaGJsTVpOLzdlZkNSSXVtQTBOTm1wSDdkeEg2bjhjVmx6L1orUlVnQzJxOWxndlpLVW9KY1lOVGpXVWZrbWtKdXRYWDJ0cjh5VnhtK2VDL2huUml5ZlZMWjJxUHhjdHZEbEJWQmZnTHVQeWM9XCJ9JyxcbiAgICBzb3VyY2U6ICd1c2VyJyxcbiAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgIHRsbmJ0Yzoge1xuICAgICAgICBwdXJwb3NlOiAnbm9kZUF1dGgnLFxuICAgICAgfSxcbiAgICB9LFxuICB9O1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG5cbiAgICBiYXNlY29pbiA9IGJpdGdvLmNvaW4oY29pbk5hbWUpO1xuICAgIHdhbGxldHMgPSBiYXNlY29pbi53YWxsZXRzKCk7XG4gICAgYmdVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzW2JpdGdvLmdldEVudigpXS51cmk7XG4gIH0pO1xuXG4gIGFmdGVyKGZ1bmN0aW9uICgpIHtcbiAgICBub2NrLmNsZWFuQWxsKCk7XG4gICAgbm9jay5wZW5kaW5nTW9ja3MoKS5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuICB9KTtcblxuICBkZXNjcmliZSgnR2VuZXJhdGUgbGlnaHRuaW5nIHdhbGxldCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHBhcmFtZXRlcnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCB3YWxsZXRzXG4gICAgICAgIC5nZW5lcmF0ZVdhbGxldCh7XG4gICAgICAgICAgcGFzc3BocmFzZTogJ3Bhc3MxMjMnLFxuICAgICAgICAgIGVudGVycHJpc2U6ICdlbnQxMjMnLFxuICAgICAgICAgIHBhc3Njb2RlRW5jcnlwdGlvbkNvZGU6ICdjb2RlMTIzJyxcbiAgICAgICAgICBzdWJUeXBlOiAnbGlnaHRuaW5nQ3VzdG9keScsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgIFwiZXJyb3IocykgcGFyc2luZyBnZW5lcmF0ZSBsaWdodG5pbmcgd2FsbGV0IHJlcXVlc3QgcGFyYW1zOiBJbnZhbGlkIHZhbHVlICd1bmRlZmluZWQnIHN1cHBsaWVkIHRvIEdlbmVyYXRlTGlnaHRuaW5nV2FsbGV0T3B0aW9ucy5sYWJlbCwgZXhwZWN0ZWQgc3RyaW5nLlwiXG4gICAgICAgICk7XG5cbiAgICAgIGF3YWl0IHdhbGxldHNcbiAgICAgICAgLmdlbmVyYXRlV2FsbGV0KHtcbiAgICAgICAgICBsYWJlbDogJ215IGxuIHdhbGxldCcsXG4gICAgICAgICAgZW50ZXJwcmlzZTogJ2VudDEyMycsXG4gICAgICAgICAgcGFzc2NvZGVFbmNyeXB0aW9uQ29kZTogJ2NvZGUxMjMnLFxuICAgICAgICAgIHN1YlR5cGU6ICdsaWdodG5pbmdDdXN0b2R5JyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgXCJlcnJvcihzKSBwYXJzaW5nIGdlbmVyYXRlIGxpZ2h0bmluZyB3YWxsZXQgcmVxdWVzdCBwYXJhbXM6IEludmFsaWQgdmFsdWUgJ3VuZGVmaW5lZCcgc3VwcGxpZWQgdG8gR2VuZXJhdGVMaWdodG5pbmdXYWxsZXRPcHRpb25zLnBhc3NwaHJhc2UsIGV4cGVjdGVkIHN0cmluZy5cIlxuICAgICAgICApO1xuXG4gICAgICBhd2FpdCB3YWxsZXRzXG4gICAgICAgIC5nZW5lcmF0ZVdhbGxldCh7XG4gICAgICAgICAgbGFiZWw6ICdteSBsbiB3YWxsZXQnLFxuICAgICAgICAgIHBhc3NwaHJhc2U6ICdwYXNzMTIzJyxcbiAgICAgICAgICBwYXNzY29kZUVuY3J5cHRpb25Db2RlOiAnY29kZTEyMycsXG4gICAgICAgICAgc3ViVHlwZTogJ2xpZ2h0bmluZ0N1c3RvZHknLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICBcImVycm9yKHMpIHBhcnNpbmcgZ2VuZXJhdGUgbGlnaHRuaW5nIHdhbGxldCByZXF1ZXN0IHBhcmFtczogSW52YWxpZCB2YWx1ZSAndW5kZWZpbmVkJyBzdXBwbGllZCB0byBHZW5lcmF0ZUxpZ2h0bmluZ1dhbGxldE9wdGlvbnMuZW50ZXJwcmlzZSwgZXhwZWN0ZWQgc3RyaW5nLlwiXG4gICAgICAgICk7XG5cbiAgICAgIGF3YWl0IHdhbGxldHNcbiAgICAgICAgLmdlbmVyYXRlV2FsbGV0KHtcbiAgICAgICAgICBsYWJlbDogJ215IGxuIHdhbGxldCcsXG4gICAgICAgICAgcGFzc3BocmFzZTogJ3Bhc3MxMjMnLFxuICAgICAgICAgIGVudGVycHJpc2U6ICdlbnQxMjMnLFxuICAgICAgICAgIHN1YlR5cGU6ICdsaWdodG5pbmdDdXN0b2R5JyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgXCJlcnJvcihzKSBwYXJzaW5nIGdlbmVyYXRlIGxpZ2h0bmluZyB3YWxsZXQgcmVxdWVzdCBwYXJhbXM6IEludmFsaWQgdmFsdWUgJ3VuZGVmaW5lZCcgc3VwcGxpZWQgdG8gR2VuZXJhdGVMaWdodG5pbmdXYWxsZXRPcHRpb25zLnBhc3Njb2RlRW5jcnlwdGlvbkNvZGUsIGV4cGVjdGVkIHN0cmluZy5cIlxuICAgICAgICApO1xuXG4gICAgICBhd2FpdCB3YWxsZXRzXG4gICAgICAgIC5nZW5lcmF0ZVdhbGxldCh7XG4gICAgICAgICAgbGFiZWw6IDEyMyBhcyBhbnksXG4gICAgICAgICAgcGFzc3BocmFzZTogJ3Bhc3MxMjMnLFxuICAgICAgICAgIGVudGVycHJpc2U6ICdlbnQxMjMnLFxuICAgICAgICAgIHBhc3Njb2RlRW5jcnlwdGlvbkNvZGU6ICdjb2RlMTIzJyxcbiAgICAgICAgICBzdWJUeXBlOiAnbGlnaHRuaW5nQ3VzdG9keScsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgIFwiZXJyb3IocykgcGFyc2luZyBnZW5lcmF0ZSBsaWdodG5pbmcgd2FsbGV0IHJlcXVlc3QgcGFyYW1zOiBJbnZhbGlkIHZhbHVlICcxMjMnIHN1cHBsaWVkIHRvIEdlbmVyYXRlTGlnaHRuaW5nV2FsbGV0T3B0aW9ucy5sYWJlbCwgZXhwZWN0ZWQgc3RyaW5nLlwiXG4gICAgICAgICk7XG5cbiAgICAgIGF3YWl0IHdhbGxldHNcbiAgICAgICAgLmdlbmVyYXRlV2FsbGV0KHtcbiAgICAgICAgICBsYWJlbDogJ215IGxuIHdhbGxldCcsXG4gICAgICAgICAgcGFzc3BocmFzZTogMTIzIGFzIGFueSxcbiAgICAgICAgICBlbnRlcnByaXNlOiAnZW50MTIzJyxcbiAgICAgICAgICBwYXNzY29kZUVuY3J5cHRpb25Db2RlOiAnY29kZTEyMycsXG4gICAgICAgICAgc3ViVHlwZTogJ2xpZ2h0bmluZ0N1c3RvZHknLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICBcImVycm9yKHMpIHBhcnNpbmcgZ2VuZXJhdGUgbGlnaHRuaW5nIHdhbGxldCByZXF1ZXN0IHBhcmFtczogSW52YWxpZCB2YWx1ZSAnMTIzJyBzdXBwbGllZCB0byBHZW5lcmF0ZUxpZ2h0bmluZ1dhbGxldE9wdGlvbnMucGFzc3BocmFzZSwgZXhwZWN0ZWQgc3RyaW5nLlwiXG4gICAgICAgICk7XG5cbiAgICAgIGF3YWl0IHdhbGxldHNcbiAgICAgICAgLmdlbmVyYXRlV2FsbGV0KHtcbiAgICAgICAgICBsYWJlbDogJ215IGxuIHdhbGxldCcsXG4gICAgICAgICAgcGFzc3BocmFzZTogJ3Bhc3MxMjMnLFxuICAgICAgICAgIGVudGVycHJpc2U6IDEyMyBhcyBhbnksXG4gICAgICAgICAgcGFzc2NvZGVFbmNyeXB0aW9uQ29kZTogJ2NvZGUxMjMnLFxuICAgICAgICAgIHN1YlR5cGU6ICdsaWdodG5pbmdDdXN0b2R5JyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgXCJlcnJvcihzKSBwYXJzaW5nIGdlbmVyYXRlIGxpZ2h0bmluZyB3YWxsZXQgcmVxdWVzdCBwYXJhbXM6IEludmFsaWQgdmFsdWUgJzEyMycgc3VwcGxpZWQgdG8gR2VuZXJhdGVMaWdodG5pbmdXYWxsZXRPcHRpb25zLmVudGVycHJpc2UsIGV4cGVjdGVkIHN0cmluZy5cIlxuICAgICAgICApO1xuXG4gICAgICBhd2FpdCB3YWxsZXRzXG4gICAgICAgIC5nZW5lcmF0ZVdhbGxldCh7XG4gICAgICAgICAgbGFiZWw6ICdteSBsbiB3YWxsZXQnLFxuICAgICAgICAgIHBhc3NwaHJhc2U6ICdwYXNzMTIzJyxcbiAgICAgICAgICBlbnRlcnByaXNlOiAnZW50MTIzJyxcbiAgICAgICAgICBwYXNzY29kZUVuY3J5cHRpb25Db2RlOiAxMjMgYXMgYW55LFxuICAgICAgICAgIHN1YlR5cGU6ICdsaWdodG5pbmdDdXN0b2R5JyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgXCJlcnJvcihzKSBwYXJzaW5nIGdlbmVyYXRlIGxpZ2h0bmluZyB3YWxsZXQgcmVxdWVzdCBwYXJhbXM6IEludmFsaWQgdmFsdWUgJzEyMycgc3VwcGxpZWQgdG8gR2VuZXJhdGVMaWdodG5pbmdXYWxsZXRPcHRpb25zLnBhc3Njb2RlRW5jcnlwdGlvbkNvZGUsIGV4cGVjdGVkIHN0cmluZy5cIlxuICAgICAgICApO1xuICAgIH0pO1xuXG4gICAgZm9yIChjb25zdCBzdWJUeXBlIG9mIFsnbGlnaHRuaW5nQ3VzdG9keScsICdsaWdodG5pbmdTZWxmQ3VzdG9keSddIGFzIGNvbnN0KSB7XG4gICAgICBpdChgc2hvdWxkIGdlbmVyYXRlICR7c3ViVHlwZX0gbGlnaHRuaW5nIHdhbGxldGAsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgcGFyYW1zOiBHZW5lcmF0ZUxpZ2h0bmluZ1dhbGxldE9wdGlvbnMgPSB7XG4gICAgICAgICAgbGFiZWw6ICdteSBsbiB3YWxsZXQnLFxuICAgICAgICAgIHBhc3NwaHJhc2U6ICdwYXNzMTIzJyxcbiAgICAgICAgICBlbnRlcnByaXNlOiAnZW50MTIzJyxcbiAgICAgICAgICBwYXNzY29kZUVuY3J5cHRpb25Db2RlOiAnY29kZTEyMycsXG4gICAgICAgICAgc3ViVHlwZTogc3ViVHlwZSBhcyAnbGlnaHRuaW5nQ3VzdG9keScgfCAnbGlnaHRuaW5nU2VsZkN1c3RvZHknLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHZhbGlkYXRlS2V5UmVxdWVzdCA9IChib2R5KSA9PiB7XG4gICAgICAgICAgY29uc3QgYmFzZUNoZWNrcyA9XG4gICAgICAgICAgICBib2R5LnB1Yi5zdGFydHNXaXRoKCd4cHViJykgJiZcbiAgICAgICAgICAgICEhYm9keS5lbmNyeXB0ZWRQcnYgJiZcbiAgICAgICAgICAgIGJvZHkua2V5VHlwZSA9PT0gJ2luZGVwZW5kZW50JyAmJlxuICAgICAgICAgICAgYm9keS5zb3VyY2UgPT09ICd1c2VyJztcblxuICAgICAgICAgIGlmIChib2R5Lm9yaWdpbmFsUGFzc2NvZGVFbmNyeXB0aW9uQ29kZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gYmFzZUNoZWNrcyAmJiBib2R5Lm9yaWdpbmFsUGFzc2NvZGVFbmNyeXB0aW9uQ29kZSA9PT0gJ2NvZGUxMjMnICYmIGJvZHkuY29pblNwZWNpZmljID09PSB1bmRlZmluZWQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGNvaW5TcGVjaWZpYyA9IGJvZHkuY29pblNwZWNpZmljICYmIGJvZHkuY29pblNwZWNpZmljLnRsbmJ0YztcbiAgICAgICAgICAgIHJldHVybiBiYXNlQ2hlY2tzICYmICEhY29pblNwZWNpZmljICYmIFsndXNlckF1dGgnLCAnbm9kZUF1dGgnXS5pbmNsdWRlcyhjb2luU3BlY2lmaWMucHVycG9zZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHZhbGlkYXRlV2FsbGV0UmVxdWVzdCA9IChib2R5KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGJvZHkubGFiZWwgPT09ICdteSBsbiB3YWxsZXQnICYmXG4gICAgICAgICAgICBib2R5Lm0gPT09IDEgJiZcbiAgICAgICAgICAgIGJvZHkubiA9PT0gMSAmJlxuICAgICAgICAgICAgYm9keS50eXBlID09PSAnaG90JyAmJlxuICAgICAgICAgICAgYm9keS5zdWJUeXBlID09PSBzdWJUeXBlICYmXG4gICAgICAgICAgICBib2R5LmVudGVycHJpc2UgPT09ICdlbnQxMjMnICYmXG4gICAgICAgICAgICBBcnJheS5pc0FycmF5KGJvZHkua2V5cykgJiZcbiAgICAgICAgICAgIGJvZHkua2V5cy5sZW5ndGggPT09IDEgJiZcbiAgICAgICAgICAgIGJvZHkua2V5c1swXSA9PT0gJ2tleUlkMScgJiZcbiAgICAgICAgICAgIGJvZHkuY29pblNwZWNpZmljICYmXG4gICAgICAgICAgICBib2R5LmNvaW5TcGVjaWZpYy50bG5idGMgJiZcbiAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoYm9keS5jb2luU3BlY2lmaWMudGxuYnRjLmtleXMpICYmXG4gICAgICAgICAgICBib2R5LmNvaW5TcGVjaWZpYy50bG5idGMua2V5cy5sZW5ndGggPT09IDIgJiZcbiAgICAgICAgICAgIGJvZHkuY29pblNwZWNpZmljLnRsbmJ0Yy5rZXlzLmluY2x1ZGVzKCdrZXlJZDInKSAmJlxuICAgICAgICAgICAgYm9keS5jb2luU3BlY2lmaWMudGxuYnRjLmtleXMuaW5jbHVkZXMoJ2tleUlkMycpXG4gICAgICAgICAgKTtcbiAgICAgICAgfTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5wb3N0KCcvYXBpL3YyLycgKyBjb2luTmFtZSArICcva2V5JywgKGJvZHkpID0+IHZhbGlkYXRlS2V5UmVxdWVzdChib2R5KSlcbiAgICAgICAgICAucmVwbHkoMjAwLCB7IGlkOiAna2V5SWQxJyB9KTtcbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAucG9zdCgnL2FwaS92Mi8nICsgY29pbk5hbWUgKyAnL2tleScsIChib2R5KSA9PiB2YWxpZGF0ZUtleVJlcXVlc3QoYm9keSkpXG4gICAgICAgICAgLnJlcGx5KDIwMCwgeyBpZDogJ2tleUlkMicgfSk7XG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLnBvc3QoJy9hcGkvdjIvJyArIGNvaW5OYW1lICsgJy9rZXknLCAoYm9keSkgPT4gdmFsaWRhdGVLZXlSZXF1ZXN0KGJvZHkpKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHsgaWQ6ICdrZXlJZDMnIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLnBvc3QoJy9hcGkvdjIvJyArIGNvaW5OYW1lICsgJy93YWxsZXQvYWRkJywgKGJvZHkpID0+IHZhbGlkYXRlV2FsbGV0UmVxdWVzdChib2R5KSlcbiAgICAgICAgICAucmVwbHkoMjAwLCB7IGlkOiAnd2FsbGV0SWQnIH0pO1xuXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgd2FsbGV0cy5nZW5lcmF0ZVdhbGxldChwYXJhbXMpO1xuXG4gICAgICAgIGFzc2VydC5vayhyZXNwb25zZS53YWxsZXQpO1xuICAgICAgICBhc3NlcnQub2socmVzcG9uc2UuZW5jcnlwdGVkV2FsbGV0UGFzc3BocmFzZSk7XG4gICAgICAgIGFzc2VydC5lcXVhbChcbiAgICAgICAgICBiaXRnby5kZWNyeXB0KHsgaW5wdXQ6IHJlc3BvbnNlLmVuY3J5cHRlZFdhbGxldFBhc3NwaHJhc2UsIHBhc3N3b3JkOiBwYXJhbXMucGFzc2NvZGVFbmNyeXB0aW9uQ29kZSB9KSxcbiAgICAgICAgICBwYXJhbXMucGFzc3BocmFzZVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfVxuICB9KTtcblxuICBkZXNjcmliZSgnaW52b2ljZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IHdhbGxldDogTGlnaHRuaW5nV2FsbGV0O1xuICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgd2FsbGV0ID0gZ2V0TGlnaHRuaW5nV2FsbGV0KFxuICAgICAgICBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlY29pbiwge1xuICAgICAgICAgIGlkOiAnd2FsbGV0SWQnLFxuICAgICAgICAgIGNvaW46ICd0bG5idGMnLFxuICAgICAgICAgIHN1YlR5cGU6ICdsaWdodG5pbmdDdXN0b2R5JyxcbiAgICAgICAgICBjb2luU3BlY2lmaWM6IHsga2V5czogWydkZWYnLCAnZ2hpJ10gfSxcbiAgICAgICAgfSlcbiAgICAgICkgYXMgTGlnaHRuaW5nV2FsbGV0O1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBsaXN0IGludm9pY2VzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW52b2ljZTogSW52b2ljZUluZm8gPSB7XG4gICAgICAgIHZhbHVlTXNhdDogMTAwMG4sXG4gICAgICAgIHBheW1lbnRIYXNoOiAnZm9vJyxcbiAgICAgICAgaW52b2ljZTogJ3RsbmZvb2JhcicsXG4gICAgICAgIHdhbGxldElkOiB3YWxsZXQud2FsbGV0LmlkKCksXG4gICAgICAgIHN0YXR1czogJ29wZW4nLFxuICAgICAgICBleHBpcmVzQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgdXBkYXRlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHF1ZXJ5ID0ge1xuICAgICAgICBzdGF0dXM6ICdvcGVuJyxcbiAgICAgICAgc3RhcnREYXRlOiBuZXcgRGF0ZSgpLFxuICAgICAgICBsaW1pdDogMTAwbixcbiAgICAgIH0gYXMgSW52b2ljZVF1ZXJ5O1xuICAgICAgY29uc3QgbGlzdEludm9pY2VzTm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoYC9hcGkvdjIvd2FsbGV0LyR7d2FsbGV0LndhbGxldC5pZCgpfS9saWdodG5pbmcvaW52b2ljZWApXG4gICAgICAgIC5xdWVyeShJbnZvaWNlUXVlcnkuZW5jb2RlKHF1ZXJ5KSlcbiAgICAgICAgLnJlcGx5KDIwMCwgW0ludm9pY2VJbmZvLmVuY29kZShpbnZvaWNlKV0pO1xuICAgICAgY29uc3QgaW52b2ljZVJlc3BvbnNlID0gYXdhaXQgd2FsbGV0Lmxpc3RJbnZvaWNlcyhxdWVyeSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaW52b2ljZVJlc3BvbnNlLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKGludm9pY2VSZXNwb25zZVswXSwgaW52b2ljZSk7XG4gICAgICBsaXN0SW52b2ljZXNOb2NrLmRvbmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdsaXN0SW52b2ljZXMgc2hvdWxkIHRocm93IGVycm9yIGlmIHdwIHJlc3BvbnNlIGlzIGludmFsaWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBsaXN0SW52b2ljZXNOb2NrID0gbm9jayhiZ1VybClcbiAgICAgICAgLmdldChgL2FwaS92Mi93YWxsZXQvJHt3YWxsZXQud2FsbGV0LmlkKCl9L2xpZ2h0bmluZy9pbnZvaWNlYClcbiAgICAgICAgLnJlcGx5KDIwMCwgW3sgdmFsdWVNc2F0OiAnMTAwMCcgfV0pO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYXN5bmMgKCkgPT4gYXdhaXQgd2FsbGV0Lmxpc3RJbnZvaWNlcyh7fSksIC9JbnZhbGlkIGxpc3QgaW52b2ljZXMgcmVzcG9uc2UvKTtcbiAgICAgIGxpc3RJbnZvaWNlc05vY2suZG9uZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgaW52b2ljZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNyZWF0ZUludm9pY2U6IENyZWF0ZUludm9pY2VCb2R5ID0ge1xuICAgICAgICB2YWx1ZU1zYXQ6IDEwMDBuLFxuICAgICAgICBtZW1vOiAndGVzdCBpbnZvaWNlJyxcbiAgICAgICAgZXhwaXJ5OiAxMDAsXG4gICAgICB9O1xuICAgICAgY29uc3QgaW52b2ljZTogSW52b2ljZSA9IHtcbiAgICAgICAgaW52b2ljZTogJ3RsbmFiYycsXG4gICAgICAgIHBheW1lbnRIYXNoOiAnMTIzJyxcbiAgICAgICAgZXhwaXJlc0F0OiBuZXcgRGF0ZSgpLFxuICAgICAgICBzdGF0dXM6ICdvcGVuJyxcbiAgICAgICAgd2FsbGV0SWQ6IHdhbGxldC53YWxsZXQuaWQoKSxcbiAgICAgICAgdmFsdWVNc2F0OiAxMDAwbixcbiAgICAgIH07XG4gICAgICBjb25zdCBjcmVhdGVJbnZvaWNlTm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5wb3N0KGAvYXBpL3YyL3dhbGxldC8ke3dhbGxldC53YWxsZXQuaWQoKX0vbGlnaHRuaW5nL2ludm9pY2VgLCBDcmVhdGVJbnZvaWNlQm9keS5lbmNvZGUoY3JlYXRlSW52b2ljZSkpXG4gICAgICAgIC5yZXBseSgyMDAsIEludm9pY2UuZW5jb2RlKGludm9pY2UpKTtcbiAgICAgIGNvbnN0IGNyZWF0ZUludm9pY2VSZXNwb25zZSA9IGF3YWl0IHdhbGxldC5jcmVhdGVJbnZvaWNlKGNyZWF0ZUludm9pY2UpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChjcmVhdGVJbnZvaWNlUmVzcG9uc2UsIGludm9pY2UpO1xuICAgICAgY3JlYXRlSW52b2ljZU5vY2suZG9uZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2NyZWF0ZUludm9pY2Ugc2hvdWxkIHRocm93IGVycm9yIGlmIHdwIHJlc3BvbnNlIGlzIGludmFsaWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjcmVhdGVJbnZvaWNlOiBDcmVhdGVJbnZvaWNlQm9keSA9IHtcbiAgICAgICAgdmFsdWVNc2F0OiAxMDAwbixcbiAgICAgICAgbWVtbzogJ3Rlc3QgaW52b2ljZScsXG4gICAgICAgIGV4cGlyeTogMTAwLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGNyZWF0ZUludm9pY2VOb2NrID0gbm9jayhiZ1VybClcbiAgICAgICAgLnBvc3QoYC9hcGkvdjIvd2FsbGV0LyR7d2FsbGV0LndhbGxldC5pZCgpfS9saWdodG5pbmcvaW52b2ljZWApXG4gICAgICAgIC5yZXBseSgyMDAsIHsgdmFsdWVNc2F0OiAnMTAwMCcgfSk7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhhc3luYyAoKSA9PiBhd2FpdCB3YWxsZXQuY3JlYXRlSW52b2ljZShjcmVhdGVJbnZvaWNlKSwgL0ludmFsaWQgY3JlYXRlIGludm9pY2UgcmVzcG9uc2UvKTtcbiAgICAgIGNyZWF0ZUludm9pY2VOb2NrLmRvbmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGF5IGludm9pY2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJhbXM6IFN1Ym1pdFBheW1lbnRQYXJhbXMgPSB7XG4gICAgICAgIGludm9pY2U6ICdsbmJjMS4uLicsXG4gICAgICAgIGFtb3VudE1zYXQ6IDEwMDBuLFxuICAgICAgICBmZWVMaW1pdE1zYXQ6IDEwMG4sXG4gICAgICAgIGZlZUxpbWl0UmF0aW86IDAuMSxcbiAgICAgICAgc2VxdWVuY2VJZDogJzEyMycsXG4gICAgICAgIGNvbW1lbnQ6ICd0ZXN0IHBheW1lbnQnLFxuICAgICAgICBwYXNzcGhyYXNlOiAncGFzc3dvcmQxMjMnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhSZXF1ZXN0UmVzcG9uc2UgPSB7XG4gICAgICAgIHR4UmVxdWVzdElkOiAndHhSZXExMjMnLFxuICAgICAgICBzdGF0ZTogJ2RlbGl2ZXJlZCcsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBsbmRSZXNwb25zZTogTG5kQ3JlYXRlUGF5bWVudFJlc3BvbnNlID0ge1xuICAgICAgICBzdGF0dXM6ICdzZXR0bGVkJyxcbiAgICAgICAgcGF5bWVudEhhc2g6ICdwYXltZW50SGFzaDEyMycsXG4gICAgICAgIGFtb3VudE1zYXQ6IHBhcmFtcy5hbW91bnRNc2F0ICE9PSB1bmRlZmluZWQgPyBwYXJhbXMuYW1vdW50TXNhdC50b1N0cmluZygpIDogdW5kZWZpbmVkLFxuICAgICAgICBmZWVNc2F0OiBwYXJhbXMuZmVlTGltaXRNc2F0ICE9PSB1bmRlZmluZWQgPyBwYXJhbXMuZmVlTGltaXRNc2F0LnRvU3RyaW5nKCkgOiB1bmRlZmluZWQsXG4gICAgICAgIHBheW1lbnRQcmVpbWFnZTogJ3ByZWltYWdlMTIzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGZpbmFsUGF5bWVudFJlc3BvbnNlID0ge1xuICAgICAgICB0eFJlcXVlc3RJZDogJ3R4UmVxMTIzJyxcbiAgICAgICAgc3RhdGU6ICdkZWxpdmVyZWQnLFxuICAgICAgICB0cmFuc2FjdGlvbnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB1bnNpZ25lZFR4OiB7XG4gICAgICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgICAgIC4uLmxuZFJlc3BvbnNlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHJhbnNmZXJEYXRhID0ge1xuICAgICAgICBpZDogJ2Zha2VfaWQnLFxuICAgICAgICBjb2luOiAndGxuYnRjJyxcbiAgICAgICAgc3RhdGU6ICdjb25maXJtZWQnLFxuICAgICAgICB0eGlkOiBsbmRSZXNwb25zZS5wYXltZW50SGFzaCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGdldFRyYW5zZmVyTm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoYC9hcGkvdjIvJHtjb2luTmFtZX0vd2FsbGV0LyR7d2FsbGV0LndhbGxldC5pZCgpfS90cmFuc2Zlci8ke2xuZFJlc3BvbnNlLnBheW1lbnRIYXNofWApXG4gICAgICAgIC5yZXBseSgyMDAsIHRyYW5zZmVyRGF0YSk7XG5cbiAgICAgIGNvbnN0IGNyZWF0ZVR4UmVxdWVzdE5vY2sgPSBub2NrKGJnVXJsKVxuICAgICAgICAucG9zdChgL2FwaS92Mi93YWxsZXQvJHt3YWxsZXQud2FsbGV0LmlkKCl9L3R4cmVxdWVzdHNgKVxuICAgICAgICAucmVwbHkoMjAwLCB0eFJlcXVlc3RSZXNwb25zZSk7XG5cbiAgICAgIGNvbnN0IHNlbmRUeFJlcXVlc3ROb2NrID0gbm9jayhiZ1VybClcbiAgICAgICAgLnBvc3QoYC9hcGkvdjIvd2FsbGV0LyR7d2FsbGV0LndhbGxldC5pZCgpfS90eHJlcXVlc3RzLyR7dHhSZXF1ZXN0UmVzcG9uc2UudHhSZXF1ZXN0SWR9L3RyYW5zYWN0aW9ucy8wL3NlbmRgKVxuICAgICAgICAucmVwbHkoMjAwLCBmaW5hbFBheW1lbnRSZXNwb25zZSk7XG5cbiAgICAgIGNvbnN0IHVzZXJBdXRoS2V5Tm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoJy9hcGkvdjIvJyArIGNvaW5OYW1lICsgJy9rZXkvZGVmJylcbiAgICAgICAgLnJlcGx5KDIwMCwgdXNlckF1dGhLZXkpO1xuICAgICAgY29uc3Qgbm9kZUF1dGhLZXlOb2NrID0gbm9jayhiZ1VybClcbiAgICAgICAgLmdldCgnL2FwaS92Mi8nICsgY29pbk5hbWUgKyAnL2tleS9naGknKVxuICAgICAgICAucmVwbHkoMjAwLCBub2RlQXV0aEtleSk7XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgd2FsbGV0LnBheUludm9pY2UocGFyYW1zKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXNwb25zZS50eFJlcXVlc3RJZCwgJ3R4UmVxMTIzJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzcG9uc2UudHhSZXF1ZXN0U3RhdGUsICdkZWxpdmVyZWQnKTtcbiAgICAgIGFzc2VydChyZXNwb25zZS5wYXltZW50U3RhdHVzKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgICAgcmVzcG9uc2UucGF5bWVudFN0YXR1cy5zdGF0dXMsXG4gICAgICAgIGZpbmFsUGF5bWVudFJlc3BvbnNlLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LmNvaW5TcGVjaWZpYy5zdGF0dXNcbiAgICAgICk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoXG4gICAgICAgIHJlc3BvbnNlLnBheW1lbnRTdGF0dXMucGF5bWVudEhhc2gsXG4gICAgICAgIGZpbmFsUGF5bWVudFJlc3BvbnNlLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LmNvaW5TcGVjaWZpYy5wYXltZW50SGFzaFxuICAgICAgKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgICAgcmVzcG9uc2UucGF5bWVudFN0YXR1cy5hbW91bnRNc2F0LFxuICAgICAgICBmaW5hbFBheW1lbnRSZXNwb25zZS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5jb2luU3BlY2lmaWMuYW1vdW50TXNhdFxuICAgICAgKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgICAgcmVzcG9uc2UucGF5bWVudFN0YXR1cy5mZWVNc2F0LFxuICAgICAgICBmaW5hbFBheW1lbnRSZXNwb25zZS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5jb2luU3BlY2lmaWMuZmVlTXNhdFxuICAgICAgKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgICAgcmVzcG9uc2UucGF5bWVudFN0YXR1cy5wYXltZW50UHJlaW1hZ2UsXG4gICAgICAgIGZpbmFsUGF5bWVudFJlc3BvbnNlLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LmNvaW5TcGVjaWZpYy5wYXltZW50UHJlaW1hZ2VcbiAgICAgICk7XG5cbiAgICAgIGdldFRyYW5zZmVyTm9jay5kb25lKCk7XG4gICAgICBjcmVhdGVUeFJlcXVlc3ROb2NrLmRvbmUoKTtcbiAgICAgIHNlbmRUeFJlcXVlc3ROb2NrLmRvbmUoKTtcbiAgICAgIHVzZXJBdXRoS2V5Tm9jay5kb25lKCk7XG4gICAgICBub2RlQXV0aEtleU5vY2suZG9uZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgcGVuZGluZyBhcHByb3ZhbCB3aGVuIHBheWluZyBpbnZvaWNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFyYW1zOiBTdWJtaXRQYXltZW50UGFyYW1zID0ge1xuICAgICAgICBpbnZvaWNlOiAnbG5iYzEuLi4nLFxuICAgICAgICBhbW91bnRNc2F0OiAxMDAwbixcbiAgICAgICAgZmVlTGltaXRNc2F0OiAxMDBuLFxuICAgICAgICBmZWVMaW1pdFJhdGlvOiAwLjEsXG4gICAgICAgIHNlcXVlbmNlSWQ6ICcxMjMnLFxuICAgICAgICBjb21tZW50OiAndGVzdCBwYXltZW50JyxcbiAgICAgICAgcGFzc3BocmFzZTogJ3Bhc3N3b3JkMTIzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UmVxdWVzdFJlc3BvbnNlID0ge1xuICAgICAgICB0eFJlcXVlc3RJZDogJ3R4UmVxMTIzJyxcbiAgICAgICAgc3RhdGU6ICdwZW5kaW5nQXBwcm92YWwnLFxuICAgICAgICBwZW5kaW5nQXBwcm92YWxJZDogJ2FwcHJvdmFsMTIzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHBlbmRpbmdBcHByb3ZhbERhdGE6IFBlbmRpbmdBcHByb3ZhbERhdGEgPSB7XG4gICAgICAgIGlkOiAnYXBwcm92YWwxMjMnLFxuICAgICAgICBzdGF0ZTogU3RhdGUuUEVORElORyxcbiAgICAgICAgY3JlYXRvcjogJ3VzZXIxMjMnLFxuICAgICAgICBpbmZvOiB7XG4gICAgICAgICAgdHlwZTogVHlwZS5UUkFOU0FDVElPTl9SRVFVRVNULFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgY3JlYXRlVHhSZXF1ZXN0Tm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5wb3N0KGAvYXBpL3YyL3dhbGxldC8ke3dhbGxldC53YWxsZXQuaWQoKX0vdHhyZXF1ZXN0c2ApXG4gICAgICAgIC5yZXBseSgyMDAsIHR4UmVxdWVzdFJlc3BvbnNlKTtcblxuICAgICAgY29uc3QgZ2V0UGVuZGluZ0FwcHJvdmFsTm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoYC9hcGkvdjIvJHtjb2luTmFtZX0vcGVuZGluZ2FwcHJvdmFscy8ke3R4UmVxdWVzdFJlc3BvbnNlLnBlbmRpbmdBcHByb3ZhbElkfWApXG4gICAgICAgIC5yZXBseSgyMDAsIHBlbmRpbmdBcHByb3ZhbERhdGEpO1xuXG4gICAgICBjb25zdCB1c2VyQXV0aEtleU5vY2sgPSBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpL3YyLycgKyBjb2luTmFtZSArICcva2V5L2RlZicpXG4gICAgICAgIC5yZXBseSgyMDAsIHVzZXJBdXRoS2V5KTtcbiAgICAgIGNvbnN0IG5vZGVBdXRoS2V5Tm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoJy9hcGkvdjIvJyArIGNvaW5OYW1lICsgJy9rZXkvZ2hpJylcbiAgICAgICAgLnJlcGx5KDIwMCwgbm9kZUF1dGhLZXkpO1xuXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHdhbGxldC5wYXlJbnZvaWNlKHBhcmFtcyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzcG9uc2UudHhSZXF1ZXN0SWQsICd0eFJlcTEyMycpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3BvbnNlLnR4UmVxdWVzdFN0YXRlLCAncGVuZGluZ0FwcHJvdmFsJyk7XG4gICAgICBhc3NlcnQocmVzcG9uc2UucGVuZGluZ0FwcHJvdmFsKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXNwb25zZS5wYXltZW50U3RhdHVzLCB1bmRlZmluZWQpO1xuXG4gICAgICBjcmVhdGVUeFJlcXVlc3ROb2NrLmRvbmUoKTtcbiAgICAgIGdldFBlbmRpbmdBcHByb3ZhbE5vY2suZG9uZSgpO1xuICAgICAgdXNlckF1dGhLZXlOb2NrLmRvbmUoKTtcbiAgICAgIG5vZGVBdXRoS2V5Tm9jay5kb25lKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdHZXQgbGlnaHRuaW5nIGtleShzKScsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB3YWxsZXREYXRhID0ge1xuICAgICAgaWQ6ICdmYWtlaWQnLFxuICAgICAgY29pbjogY29pbk5hbWUsXG4gICAgICBrZXlzOiBbJ2FiYyddLFxuICAgICAgY29pblNwZWNpZmljOiB7IGtleXM6IFsnZGVmJywgJ2doaSddIH0sXG4gICAgICBzdWJUeXBlOiAnbGlnaHRuaW5nQ3VzdG9keScsXG4gICAgfTtcblxuICAgIGNvbnN0IHVzZXJLZXlEYXRhID0ge1xuICAgICAgaWQ6ICdhYmMnLFxuICAgICAgcHViOiAneHB1YjEnLFxuICAgICAgZW5jcnlwdGVkUHJ2OiAnZW5jcnlwdGVkUHJ2MScsXG4gICAgICBzb3VyY2U6ICd1c2VyJyxcbiAgICB9O1xuXG4gICAgY29uc3QgdXNlckF1dGhLZXlEYXRhID0ge1xuICAgICAgaWQ6ICdkZWYnLFxuICAgICAgcHViOiAneHB1YjInLFxuICAgICAgZW5jcnlwdGVkUHJ2OiAnZW5jcnlwdGVkUHJ2MicsXG4gICAgICBzb3VyY2U6ICd1c2VyJyxcbiAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICB0bG5idGM6IHtcbiAgICAgICAgICBwdXJwb3NlOiAndXNlckF1dGgnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgY29uc3Qgbm9kZUF1dGhLZXlEYXRhID0ge1xuICAgICAgaWQ6ICdnaGknLFxuICAgICAgcHViOiAneHB1YjMnLFxuICAgICAgZW5jcnlwdGVkUHJ2OiAnZW5jcnlwdGVkUHJ2MycsXG4gICAgICBzb3VyY2U6ICd1c2VyJyxcbiAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICB0bG5idGM6IHtcbiAgICAgICAgICBwdXJwb3NlOiAnbm9kZUF1dGgnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgaXQoJ3Nob3VsZCBnZXQgbGlnaHRuaW5nIGtleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB3YWxsZXREYXRhKTtcblxuICAgICAgY29uc3Qga2V5Tm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoJy9hcGkvdjIvJyArIGNvaW5OYW1lICsgJy9rZXkvYWJjJylcbiAgICAgICAgLnJlcGx5KDIwMCwgdXNlcktleURhdGEpO1xuXG4gICAgICBjb25zdCBrZXkgPSBhd2FpdCBnZXRMaWdodG5pbmdLZXljaGFpbih3YWxsZXQpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChrZXksIHVzZXJLZXlEYXRhKTtcbiAgICAgIGtleU5vY2suZG9uZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZXQgbGlnaHRuaW5nIGF1dGgga2V5cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB3YWxsZXREYXRhKTtcblxuICAgICAgY29uc3QgdXNlckF1dGhLZXlOb2NrID0gbm9jayhiZ1VybClcbiAgICAgICAgLmdldCgnL2FwaS92Mi8nICsgY29pbk5hbWUgKyAnL2tleS9kZWYnKVxuICAgICAgICAucmVwbHkoMjAwLCB1c2VyQXV0aEtleURhdGEpO1xuICAgICAgY29uc3Qgbm9kZUF1dGhLZXlOb2NrID0gbm9jayhiZ1VybClcbiAgICAgICAgLmdldCgnL2FwaS92Mi8nICsgY29pbk5hbWUgKyAnL2tleS9naGknKVxuICAgICAgICAucmVwbHkoMjAwLCBub2RlQXV0aEtleURhdGEpO1xuXG4gICAgICBjb25zdCB7IHVzZXJBdXRoS2V5LCBub2RlQXV0aEtleSB9ID0gYXdhaXQgZ2V0TGlnaHRuaW5nQXV0aEtleWNoYWlucyh3YWxsZXQpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbCh1c2VyQXV0aEtleSwgdXNlckF1dGhLZXlEYXRhKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwobm9kZUF1dGhLZXksIG5vZGVBdXRoS2V5RGF0YSk7XG4gICAgICB1c2VyQXV0aEtleU5vY2suZG9uZSgpO1xuICAgICAgbm9kZUF1dGhLZXlOb2NrLmRvbmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBnZXQgbGlnaHRuaW5nIGtleSBmb3IgaW52YWxpZCBudW1iZXIgb2Yga2V5cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB7IC4uLndhbGxldERhdGEsIGtleXM6IFtdIH0pO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgIGFzeW5jICgpID0+IGF3YWl0IGdldExpZ2h0bmluZ0tleWNoYWluKHdhbGxldCksXG4gICAgICAgIC9FcnJvcjogSW52YWxpZCBudW1iZXIgb2Yga2V5IGluIGxpZ2h0bmluZyB3YWxsZXQ6IDAvXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIGdldCBsaWdodG5pbmcgYXV0aCBrZXlzIGZvciBpbnZhbGlkIG51bWJlciBvZiBrZXlzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHsgLi4ud2FsbGV0RGF0YSwgY29pblNwZWNpZmljOiB7IGtleXM6IFsnZGVmJ10gfSB9KTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICBhc3luYyAoKSA9PiBhd2FpdCBnZXRMaWdodG5pbmdBdXRoS2V5Y2hhaW5zKHdhbGxldCksXG4gICAgICAgIC9FcnJvcjogSW52YWxpZCBudW1iZXIgb2YgYXV0aCBrZXlzIGluIGxpZ2h0bmluZyB3YWxsZXQ6IDEvXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIGdldCBsaWdodG5pbmcga2V5IGZvciBpbnZhbGlkIHJlc3BvbnNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHdhbGxldERhdGEpO1xuXG4gICAgICBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpL3YyLycgKyBjb2luTmFtZSArICcva2V5L2FiYycpXG4gICAgICAgIC5yZXBseSgyMDAsIHsgLi4udXNlcktleURhdGEsIHNvdXJjZTogJ2JhY2t1cCcgfSk7XG5cbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IGF3YWl0IGdldExpZ2h0bmluZ0tleWNoYWluKHdhbGxldCksIC9FcnJvcjogSW52YWxpZCB1c2VyIGtleS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIGdldCBsaWdodG5pbmcgYXV0aCBrZXlzIGZvciBpbnZhbGlkIHJlc3BvbnNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHdhbGxldERhdGEpO1xuXG4gICAgICBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpL3YyLycgKyBjb2luTmFtZSArICcva2V5L2RlZicpXG4gICAgICAgIC5yZXBseSgyMDAsIHsgLi4udXNlckF1dGhLZXlEYXRhLCBzb3VyY2U6ICdiYWNrdXAnIH0pO1xuXG4gICAgICBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpL3YyLycgKyBjb2luTmFtZSArICcva2V5L2doaScpXG4gICAgICAgIC5yZXBseSgyMDAsIG5vZGVBdXRoS2V5RGF0YSk7XG5cbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICBhc3luYyAoKSA9PiBhd2FpdCBnZXRMaWdodG5pbmdBdXRoS2V5Y2hhaW5zKHdhbGxldCksXG4gICAgICAgIC9FcnJvcjogSW52YWxpZCBsaWdodG5pbmcgYXV0aCBrZXk6IGRlZi9cbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdVcGRhdGUgbGlnaHRuaW5nIHdhbGxldCBjb2luIHNwZWNpZmljJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHdhbGxldERhdGEgPSB7XG4gICAgICBpZDogJ2Zha2VpZCcsXG4gICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgIGtleXM6IFsnYWJjJ10sXG4gICAgICBjb2luU3BlY2lmaWM6IHsga2V5czogWydkZWYnLCAnZ2hpJ10gfSxcbiAgICAgIHN1YlR5cGU6ICdsaWdodG5pbmdTZWxmQ3VzdG9keScsXG4gICAgfTtcblxuICAgIGNvbnN0IHdhdGNoT25seUFjY291bnRzID0ge1xuICAgICAgbWFzdGVyX2tleV9iaXJ0aGRheV90aW1lc3RhbXA6ICdkdW1teScsXG4gICAgICBtYXN0ZXJfa2V5X2ZpbmdlcnByaW50OiAnZHVtbXknLFxuICAgICAgYWNjb3VudHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHhwdWI6ICd1cHViNUVlcDdINXEzOVB6UVpMVkVZTEJ5dER5Qk5lVjc0RThtUXN5ZUw2VW96RnE5WTNNc1o1Mkc3WUd1cXJKUGdveUFxRjdUQmVKZG5rckhyVnJCNXBrV2tQSjljSkdBZVBNVTZGMUd5dzZhRkgnLFxuICAgICAgICAgIHB1cnBvc2U6IDQ5LFxuICAgICAgICAgIGNvaW5fdHlwZTogMCxcbiAgICAgICAgICBhY2NvdW50OiAwLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgeHB1YjogJ3ZwdWI1WlUxUEhHcFFvRFNIY2tZaWNvNG5zdndzRDNtVGg2VWpxTDV6eUdXWFpYekJqVFlNTktvdDd0OWVSUFFZNzFoSmNuTk45cjFzczI1ZzN4QTlybW9KNW5XUGc4akVXYXZydHRuc1ZhMXF3MScsXG4gICAgICAgICAgcHVycG9zZTogODQsXG4gICAgICAgICAgY29pbl90eXBlOiAwLFxuICAgICAgICAgIGFjY291bnQ6IDAsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG4gICAgaXQoJ3Nob3VsZCB1cGRhdGUgd2FsbGV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHdhbGxldERhdGEpO1xuXG4gICAgICBjb25zdCB1c2VyQXV0aEtleU5vY2sgPSBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpL3YyLycgKyBjb2luTmFtZSArICcva2V5L2RlZicpXG4gICAgICAgIC5yZXBseSgyMDAsIHVzZXJBdXRoS2V5KTtcbiAgICAgIGNvbnN0IG5vZGVBdXRoS2V5Tm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoJy9hcGkvdjIvJyArIGNvaW5OYW1lICsgJy9rZXkvZ2hpJylcbiAgICAgICAgLnJlcGx5KDIwMCwgbm9kZUF1dGhLZXkpO1xuICAgICAgbGV0IGNhcHR1cmVkQm9keTtcbiAgICAgIGNvbnN0IHdwV2FsbGV0VXBkYXRlTm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5wdXQoYC9hcGkvdjIvdGxuYnRjL3dhbGxldC8ke3dhbGxldERhdGEuaWR9YClcbiAgICAgICAgLnJlcGx5KGZ1bmN0aW9uICh1cmksIHJlcXVlc3RCb2R5KSB7XG4gICAgICAgICAgY2FwdHVyZWRCb2R5ID0gcmVxdWVzdEJvZHk7XG4gICAgICAgICAgcmV0dXJuIFsyMDBdO1xuICAgICAgICB9KTtcblxuICAgICAgY29uc3QgcGFyYW1zOiBVcGRhdGVMaWdodG5pbmdXYWxsZXRDbGllbnRSZXF1ZXN0ID0ge1xuICAgICAgICBzaWduZXJNYWNhcm9vbjogJ3NpZ25lck1hY2Fyb29uJyxcbiAgICAgICAgc2lnbmVyQWRtaW5NYWNhcm9vbjogJ3NpZ25lckFkbWluTWFjYXJvb24nLFxuICAgICAgICBzaWduZXJUbHNLZXk6ICdzaWduZXJUbHNLZXknLFxuICAgICAgICBzaWduZXJUbHNDZXJ0OiAnc2lnbmVyVGxzQ2VydCcsXG4gICAgICAgIHdhdGNoT25seUFjY291bnRzLFxuICAgICAgICBwYXNzcGhyYXNlOiAncGFzc3dvcmQxMjMnLFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgYXNzZXJ0LmRvZXNOb3RSZWplY3QoYXN5bmMgKCkgPT4gYXdhaXQgdXBkYXRlV2FsbGV0Q29pblNwZWNpZmljKHdhbGxldCwgcGFyYW1zKSk7XG4gICAgICBhc3NlcnQodXNlckF1dGhLZXlOb2NrLmlzRG9uZSgpKTtcbiAgICAgIGFzc2VydChub2RlQXV0aEtleU5vY2suaXNEb25lKCkpO1xuICAgICAgYXNzZXJ0KHdwV2FsbGV0VXBkYXRlTm9jay5pc0RvbmUoKSk7XG5cbiAgICAgIC8vIFZlcmlmeSBzdHJ1Y3R1cmUgYW5kIHJlcXVpcmVkIGZpZWxkc1xuICAgICAgYXNzZXJ0Lm9rKGNhcHR1cmVkQm9keS5jb2luU3BlY2lmaWM/LnRsbmJ0Yz8uc2lnbmVkUmVxdWVzdCwgJ3NpZ25lZFJlcXVlc3Qgc2hvdWxkIGV4aXN0Jyk7XG4gICAgICBjb25zdCBzaWduZWRSZXF1ZXN0ID0gY2FwdHVyZWRCb2R5LmNvaW5TcGVjaWZpYy50bG5idGMuc2lnbmVkUmVxdWVzdDtcblxuICAgICAgYXNzZXJ0Lm9rKHNpZ25lZFJlcXVlc3Quc2lnbmVyVGxzQ2VydCwgJ3NpZ25lclRsc0NlcnQgc2hvdWxkIGV4aXN0Jyk7XG4gICAgICBhc3NlcnQub2soc2lnbmVkUmVxdWVzdC53YXRjaE9ubHlBY2NvdW50cywgJ3dhdGNoT25seUFjY291bnRzIHNob3VsZCBleGlzdCcpO1xuICAgICAgYXNzZXJ0Lm9rKHNpZ25lZFJlcXVlc3QuZW5jcnlwdGVkU2lnbmVyVGxzS2V5LCAnZW5jcnlwdGVkU2lnbmVyVGxzS2V5IHNob3VsZCBleGlzdCcpO1xuICAgICAgYXNzZXJ0Lm9rKHNpZ25lZFJlcXVlc3QuZW5jcnlwdGVkU2lnbmVyQWRtaW5NYWNhcm9vbiwgJ2VuY3J5cHRlZFNpZ25lckFkbWluTWFjYXJvb24gc2hvdWxkIGV4aXN0Jyk7XG4gICAgICBhc3NlcnQub2soc2lnbmVkUmVxdWVzdC5lbmNyeXB0ZWRTaWduZXJNYWNhcm9vbiwgJ2VuY3J5cHRlZFNpZ25lck1hY2Fyb29uIHNob3VsZCBleGlzdCcpO1xuXG4gICAgICAvLyBWZXJpZnkgc2lnbmF0dXJlIGV4aXN0c1xuICAgICAgYXNzZXJ0Lm9rKGNhcHR1cmVkQm9keS5jb2luU3BlY2lmaWMudGxuYnRjLnNpZ25hdHVyZSwgJ3NpZ25hdHVyZSBzaG91bGQgZXhpc3QnKTtcblxuICAgICAgLy8gd2Ugc2hvdWxkIG5vdCBwYXNzIHBhc3NwaHJhc2UgdG8gdGhlIGJhY2tlbmRcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaWduZWRSZXF1ZXN0LnBhc3NwaHJhc2UsIHVuZGVmaW5lZCwgJ3Bhc3NwaHJhc2Ugc2hvdWxkIG5vdCBleGlzdCBpbiByZXF1ZXN0Jyk7XG4gICAgfSk7XG4gIH0pO1xuICBkZXNjcmliZSgnT24gY2hhaW4gd2l0aGRyYXdhbCcsIGZ1bmN0aW9uICgpIHtcbiAgICBsZXQgd2FsbGV0OiBMaWdodG5pbmdXYWxsZXQ7XG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB3YWxsZXQgPSBnZXRMaWdodG5pbmdXYWxsZXQoXG4gICAgICAgIG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB7XG4gICAgICAgICAgaWQ6ICd3YWxsZXRJZCcsXG4gICAgICAgICAgY29pbjogJ3RsbmJ0YycsXG4gICAgICAgICAgc3ViVHlwZTogJ2xpZ2h0bmluZ0N1c3RvZHknLFxuICAgICAgICAgIGNvaW5TcGVjaWZpYzogeyBrZXlzOiBbJ2RlZicsICdnaGknXSB9LFxuICAgICAgICB9KVxuICAgICAgKSBhcyBMaWdodG5pbmdXYWxsZXQ7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCB3aXRoZHJhdyBvbiBjaGFpbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcmFtczogTGlnaHRuaW5nT25jaGFpbldpdGhkcmF3UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYW1vdW50U2F0OiA1MDAwMDBuLFxuICAgICAgICAgICAgYWRkcmVzczogJ2JjcnQxcWpxNDhjcWsydTgwaGV3ZGNuZGY1MzltOG5ubnZ0ODQ1bmw2OHg3JyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBzYXRzUGVyVmJ5dGU6IDE1bixcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UmVxdWVzdFJlc3BvbnNlID0ge1xuICAgICAgICB0eFJlcXVlc3RJZDogJ3R4UmVxMTIzJyxcbiAgICAgICAgc3RhdGU6ICdwZW5kaW5nRGVsaXZlcnknLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZmluYWxQYXltZW50UmVzcG9uc2UgPSB7XG4gICAgICAgIHR4UmVxdWVzdElkOiAndHhSZXExMjMnLFxuICAgICAgICBzdGF0ZTogJ2RlbGl2ZXJlZCcsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBjcmVhdGVUeFJlcXVlc3ROb2NrID0gbm9jayhiZ1VybClcbiAgICAgICAgLnBvc3QoYC9hcGkvdjIvd2FsbGV0LyR7d2FsbGV0LndhbGxldC5pZCgpfS90eHJlcXVlc3RzYClcbiAgICAgICAgLnJlcGx5KDIwMCwgdHhSZXF1ZXN0UmVzcG9uc2UpO1xuXG4gICAgICBjb25zdCBzZW5kVHhSZXF1ZXN0Tm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5wb3N0KGAvYXBpL3YyL3dhbGxldC8ke3dhbGxldC53YWxsZXQuaWQoKX0vdHhyZXF1ZXN0cy8ke3R4UmVxdWVzdFJlc3BvbnNlLnR4UmVxdWVzdElkfS90cmFuc2FjdGlvbnMvMC9zZW5kYClcbiAgICAgICAgLnJlcGx5KDIwMCwgZmluYWxQYXltZW50UmVzcG9uc2UpO1xuXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHdhbGxldC53aXRoZHJhd09uY2hhaW4ocGFyYW1zKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXNwb25zZS50eFJlcXVlc3RJZCwgJ3R4UmVxMTIzJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzcG9uc2UudHhSZXF1ZXN0U3RhdGUsICdkZWxpdmVyZWQnKTtcblxuICAgICAgY3JlYXRlVHhSZXF1ZXN0Tm9jay5kb25lKCk7XG4gICAgICBzZW5kVHhSZXF1ZXN0Tm9jay5kb25lKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBwZW5kaW5nIGFwcHJvdmFsIHdoZW4gd2l0aGRyYXdpbmcgb25jaGFpbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcmFtczogTGlnaHRuaW5nT25jaGFpbldpdGhkcmF3UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYW1vdW50U2F0OiA1MDAwMDBuLFxuICAgICAgICAgICAgYWRkcmVzczogJ2JjcnQxcWpxNDhjcWsydTgwaGV3ZGNuZGY1MzltOG5ubnZ0ODQ1bmw2OHg3JyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBzYXRzUGVyVmJ5dGU6IDE1bixcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UmVxdWVzdFJlc3BvbnNlID0ge1xuICAgICAgICB0eFJlcXVlc3RJZDogJ3R4UmVxMTIzJyxcbiAgICAgICAgc3RhdGU6ICdwZW5kaW5nQXBwcm92YWwnLFxuICAgICAgICBwZW5kaW5nQXBwcm92YWxJZDogJ2FwcHJvdmFsMTIzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHBlbmRpbmdBcHByb3ZhbERhdGE6IFBlbmRpbmdBcHByb3ZhbERhdGEgPSB7XG4gICAgICAgIGlkOiAnYXBwcm92YWwxMjMnLFxuICAgICAgICBzdGF0ZTogU3RhdGUuUEVORElORyxcbiAgICAgICAgY3JlYXRvcjogJ3VzZXIxMjMnLFxuICAgICAgICBpbmZvOiB7XG4gICAgICAgICAgdHlwZTogVHlwZS5UUkFOU0FDVElPTl9SRVFVRVNULFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgY3JlYXRlVHhSZXF1ZXN0Tm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5wb3N0KGAvYXBpL3YyL3dhbGxldC8ke3dhbGxldC53YWxsZXQuaWQoKX0vdHhyZXF1ZXN0c2ApXG4gICAgICAgIC5yZXBseSgyMDAsIHR4UmVxdWVzdFJlc3BvbnNlKTtcblxuICAgICAgY29uc3QgZ2V0UGVuZGluZ0FwcHJvdmFsTm9jayA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoYC9hcGkvdjIvJHtjb2luTmFtZX0vcGVuZGluZ2FwcHJvdmFscy8ke3R4UmVxdWVzdFJlc3BvbnNlLnBlbmRpbmdBcHByb3ZhbElkfWApXG4gICAgICAgIC5yZXBseSgyMDAsIHBlbmRpbmdBcHByb3ZhbERhdGEpO1xuXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHdhbGxldC53aXRoZHJhd09uY2hhaW4ocGFyYW1zKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXNwb25zZS50eFJlcXVlc3RJZCwgJ3R4UmVxMTIzJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzcG9uc2UudHhSZXF1ZXN0U3RhdGUsICdwZW5kaW5nQXBwcm92YWwnKTtcbiAgICAgIGFzc2VydChyZXNwb25zZS5wZW5kaW5nQXBwcm92YWwpO1xuXG4gICAgICBjcmVhdGVUeFJlcXVlc3ROb2NrLmRvbmUoKTtcbiAgICAgIGdldFBlbmRpbmdBcHByb3ZhbE5vY2suZG9uZSgpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19

Выполнить команду


Для локальной разработки. Не используйте в интернете!