@bitgo-beta/abstract-eth 1.2.3-alpha.40 → 1.2.3-alpha.401
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1760 -0
- package/dist/src/abstractEthLikeCoin.d.ts +18 -9
- package/dist/src/abstractEthLikeCoin.d.ts.map +1 -1
- package/dist/src/abstractEthLikeCoin.js +39 -15
- package/dist/src/abstractEthLikeNewCoins.d.ts +749 -0
- package/dist/src/abstractEthLikeNewCoins.d.ts.map +1 -0
- package/dist/src/abstractEthLikeNewCoins.js +2229 -0
- package/dist/src/ethLikeToken.d.ts +36 -6
- package/dist/src/ethLikeToken.d.ts.map +1 -1
- package/dist/src/ethLikeToken.js +286 -10
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -2
- package/dist/src/lib/contractCall.d.ts +8 -0
- package/dist/src/lib/contractCall.d.ts.map +1 -0
- package/dist/src/lib/contractCall.js +17 -0
- package/dist/src/lib/iface.d.ts +133 -0
- package/dist/src/lib/iface.d.ts.map +1 -0
- package/dist/src/lib/iface.js +8 -0
- package/dist/src/lib/index.d.ts +16 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +57 -0
- package/dist/src/lib/keyPair.d.ts +26 -0
- package/dist/src/lib/keyPair.d.ts.map +1 -0
- package/dist/src/lib/keyPair.js +65 -0
- package/dist/src/lib/messages/eip191/eip191Message.d.ts +12 -0
- package/dist/src/lib/messages/eip191/eip191Message.d.ts.map +1 -0
- package/dist/src/lib/messages/eip191/eip191Message.js +25 -0
- package/dist/src/lib/messages/eip191/eip191MessageBuilder.d.ts +19 -0
- package/dist/src/lib/messages/eip191/eip191MessageBuilder.d.ts.map +1 -0
- package/dist/src/lib/messages/eip191/eip191MessageBuilder.js +27 -0
- package/dist/src/lib/messages/eip191/index.d.ts +3 -0
- package/dist/src/lib/messages/eip191/index.d.ts.map +1 -0
- package/dist/src/lib/messages/eip191/index.js +19 -0
- package/dist/src/lib/messages/eip712/eip712Message.d.ts +6 -0
- package/dist/src/lib/messages/eip712/eip712Message.d.ts.map +1 -0
- package/dist/src/lib/messages/eip712/eip712Message.js +27 -0
- package/dist/src/lib/messages/eip712/eip712MessageBuilder.d.ts +7 -0
- package/dist/src/lib/messages/eip712/eip712MessageBuilder.d.ts.map +1 -0
- package/dist/src/lib/messages/eip712/eip712MessageBuilder.js +15 -0
- package/dist/src/lib/messages/eip712/index.d.ts +3 -0
- package/dist/src/lib/messages/eip712/index.d.ts.map +1 -0
- package/dist/src/lib/messages/eip712/index.js +19 -0
- package/dist/src/lib/messages/index.d.ts +4 -0
- package/dist/src/lib/messages/index.d.ts.map +1 -0
- package/dist/src/lib/messages/index.js +20 -0
- package/dist/src/lib/messages/messageBuilderFactory.d.ts +7 -0
- package/dist/src/lib/messages/messageBuilderFactory.d.ts.map +1 -0
- package/dist/src/lib/messages/messageBuilderFactory.js +23 -0
- package/dist/src/lib/transaction.d.ts +67 -0
- package/dist/src/lib/transaction.d.ts.map +1 -0
- package/dist/src/lib/transaction.js +142 -0
- package/dist/src/lib/transactionBuilder.d.ts +270 -0
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
- package/dist/src/lib/transactionBuilder.js +822 -0
- package/dist/src/lib/transferBuilder.d.ts +76 -0
- package/dist/src/lib/transferBuilder.d.ts.map +1 -0
- package/dist/src/lib/transferBuilder.js +307 -0
- package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts +54 -0
- package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.js +120 -0
- package/dist/src/lib/transferBuilders/index.d.ts +4 -0
- package/dist/src/lib/transferBuilders/index.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/index.js +20 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts +17 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC1155.js +96 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts +16 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC721.js +81 -0
- package/dist/src/lib/types.d.ts +39 -0
- package/dist/src/lib/types.d.ts.map +1 -0
- package/dist/src/lib/types.js +137 -0
- package/dist/src/lib/utils.d.ts +310 -0
- package/dist/src/lib/utils.d.ts.map +1 -0
- package/dist/src/lib/utils.js +829 -0
- package/dist/src/lib/walletUtil.d.ts +40 -0
- package/dist/src/lib/walletUtil.d.ts.map +1 -0
- package/dist/src/lib/walletUtil.js +43 -0
- package/dist/src/types.d.ts +9 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +3 -0
- package/dist/test/index.d.ts +2 -0
- package/dist/test/index.d.ts.map +1 -0
- package/dist/test/index.js +18 -0
- package/dist/test/unit/coin.d.ts +8 -0
- package/dist/test/unit/coin.d.ts.map +1 -0
- package/dist/test/unit/coin.js +577 -0
- package/dist/test/unit/index.d.ts +6 -0
- package/dist/test/unit/index.d.ts.map +1 -0
- package/dist/test/unit/index.js +22 -0
- package/dist/test/unit/messages/abstractEthMessageBuilderTests.d.ts +3 -0
- package/dist/test/unit/messages/abstractEthMessageBuilderTests.d.ts.map +1 -0
- package/dist/test/unit/messages/abstractEthMessageBuilderTests.js +110 -0
- package/dist/test/unit/messages/abstractEthMessageTestTypes.d.ts +43 -0
- package/dist/test/unit/messages/abstractEthMessageTestTypes.d.ts.map +1 -0
- package/dist/test/unit/messages/abstractEthMessageTestTypes.js +3 -0
- package/dist/test/unit/messages/abstractEthMessagesTests.d.ts +3 -0
- package/dist/test/unit/messages/abstractEthMessagesTests.d.ts.map +1 -0
- package/dist/test/unit/messages/abstractEthMessagesTests.js +129 -0
- package/dist/test/unit/messages/eip191/eip191Message.d.ts +2 -0
- package/dist/test/unit/messages/eip191/eip191Message.d.ts.map +1 -0
- package/dist/test/unit/messages/eip191/eip191Message.js +15 -0
- package/dist/test/unit/messages/eip191/eip191MessageBuilder.d.ts +2 -0
- package/dist/test/unit/messages/eip191/eip191MessageBuilder.d.ts.map +1 -0
- package/dist/test/unit/messages/eip191/eip191MessageBuilder.js +16 -0
- package/dist/test/unit/messages/eip191/fixtures.d.ts +109 -0
- package/dist/test/unit/messages/eip191/fixtures.d.ts.map +1 -0
- package/dist/test/unit/messages/eip191/fixtures.js +63 -0
- package/dist/test/unit/messages/eip712/eip712Message.d.ts +2 -0
- package/dist/test/unit/messages/eip712/eip712Message.d.ts.map +1 -0
- package/dist/test/unit/messages/eip712/eip712Message.js +15 -0
- package/dist/test/unit/messages/eip712/eip712MessageBuilder.d.ts +2 -0
- package/dist/test/unit/messages/eip712/eip712MessageBuilder.d.ts.map +1 -0
- package/dist/test/unit/messages/eip712/eip712MessageBuilder.js +16 -0
- package/dist/test/unit/messages/eip712/fixtures.d.ts +76 -0
- package/dist/test/unit/messages/eip712/fixtures.d.ts.map +1 -0
- package/dist/test/unit/messages/eip712/fixtures.js +120 -0
- package/dist/test/unit/messages/index.d.ts +4 -0
- package/dist/test/unit/messages/index.d.ts.map +1 -0
- package/dist/test/unit/messages/index.js +20 -0
- package/dist/test/unit/messages/messageBuilderFactory.d.ts +2 -0
- package/dist/test/unit/messages/messageBuilderFactory.d.ts.map +1 -0
- package/dist/test/unit/messages/messageBuilderFactory.js +52 -0
- package/dist/test/unit/token.d.ts +2 -0
- package/dist/test/unit/token.d.ts.map +1 -0
- package/dist/test/unit/token.js +37 -0
- package/dist/test/unit/transaction.d.ts +3 -0
- package/dist/test/unit/transaction.d.ts.map +1 -0
- package/dist/test/unit/transaction.js +60 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.d.ts +8 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.js +95 -0
- package/dist/test/unit/transactionBuilder/flushNft.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/flushNft.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/flushNft.js +381 -0
- package/dist/test/unit/transactionBuilder/index.d.ts +5 -0
- package/dist/test/unit/transactionBuilder/index.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/index.js +21 -0
- package/dist/test/unit/transactionBuilder/send.d.ts +3 -0
- package/dist/test/unit/transactionBuilder/send.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/send.js +197 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.d.ts +10 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.js +124 -0
- package/dist/test/unit/transferBuilder.d.ts +2 -0
- package/dist/test/unit/transferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transferBuilder.js +76 -0
- package/dist/test/unit/utils.d.ts +2 -0
- package/dist/test/unit/utils.d.ts.map +1 -0
- package/dist/test/unit/utils.js +184 -0
- package/dist/tsconfig.tsbuildinfo +1 -8244
- package/index.ts +2 -0
- package/package.json +30 -9
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.runBasicCoinInfoTests = runBasicCoinInfoTests;
|
|
40
|
+
exports.runExplainTransactionTests = runExplainTransactionTests;
|
|
41
|
+
exports.runSignTransactionTests = runSignTransactionTests;
|
|
42
|
+
exports.runTransactionVerificationTests = runTransactionVerificationTests;
|
|
43
|
+
exports.runRecoveryTransactionTests = runRecoveryTransactionTests;
|
|
44
|
+
const sdk_test_1 = require("@bitgo-beta/sdk-test");
|
|
45
|
+
const secp256k1_1 = require("@bitgo-beta/secp256k1");
|
|
46
|
+
const secp256k1 = __importStar(require("secp256k1"));
|
|
47
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
48
|
+
const nock_1 = __importDefault(require("nock"));
|
|
49
|
+
const should = __importStar(require("should"));
|
|
50
|
+
const src_1 = require("../../src");
|
|
51
|
+
nock_1.default.enableNetConnect();
|
|
52
|
+
function runBasicCoinInfoTests(coinName, bitgo, MainCoin, TestCoin, testData) {
|
|
53
|
+
describe(`${coinName} basic info test`, () => {
|
|
54
|
+
const coinTest = testData.COIN;
|
|
55
|
+
const coinMain = coinTest.slice(1);
|
|
56
|
+
it(`should return the right info for ${coinMain}`, () => {
|
|
57
|
+
const coin = bitgo.coin(coinMain);
|
|
58
|
+
coin.should.be.an.instanceof(MainCoin);
|
|
59
|
+
coin.getChain().should.equal(coinMain);
|
|
60
|
+
coin.getFamily().should.equal(coinMain);
|
|
61
|
+
coin.getFullName().should.equal(testData.CHAIN_FULL_NAME);
|
|
62
|
+
coin.getBaseFactor().should.equal(1e18);
|
|
63
|
+
});
|
|
64
|
+
it(`should return the right info for ${coinTest}`, () => {
|
|
65
|
+
const coin = bitgo.coin(coinTest);
|
|
66
|
+
coin.should.be.an.instanceof(TestCoin);
|
|
67
|
+
coin.getChain().should.equal(coinTest);
|
|
68
|
+
coin.getFamily().should.equal(coinMain);
|
|
69
|
+
coin.getFullName().should.equal(`Testnet ${testData.CHAIN_FULL_NAME}`);
|
|
70
|
+
coin.getBaseFactor().should.equal(1e18);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function runExplainTransactionTests(coinName, txBuilder, basecoin, testData) {
|
|
75
|
+
describe(`${coinName} explain transaction`, () => {
|
|
76
|
+
const coinTest = testData.COIN;
|
|
77
|
+
/**
|
|
78
|
+
* Build an unsigned account-lib multi-signature send transactino
|
|
79
|
+
* @param destination The destination address of the transaction
|
|
80
|
+
* @param contractAddress The address of the smart contract processing the transaction
|
|
81
|
+
* @param contractSequenceId The sequence id of the contract
|
|
82
|
+
* @param nonce The nonce of the sending address
|
|
83
|
+
* @param expireTime The expire time of the transaction
|
|
84
|
+
* @param amount The amount to send to the recipient
|
|
85
|
+
* @param gasPrice The gas price of the transaction
|
|
86
|
+
* @param gasLimit The gas limit of the transaction
|
|
87
|
+
*/
|
|
88
|
+
const buildUnsignedTransaction = async function ({ destination, contractAddress, contractSequenceId = 1, nonce = 0, expireTime = Math.floor(new Date().getTime() / 1000), amount = '100000', gasPrice = '10000', gasLimit = '20000', }) {
|
|
89
|
+
txBuilder.type(sdk_core_1.TransactionType.Send);
|
|
90
|
+
txBuilder.fee({
|
|
91
|
+
fee: gasPrice,
|
|
92
|
+
gasLimit: gasLimit,
|
|
93
|
+
});
|
|
94
|
+
txBuilder.counter(nonce);
|
|
95
|
+
txBuilder.contract(contractAddress);
|
|
96
|
+
const transferBuilder = txBuilder.transfer();
|
|
97
|
+
transferBuilder
|
|
98
|
+
.coin(coinTest)
|
|
99
|
+
.expirationTime(expireTime)
|
|
100
|
+
.amount(amount)
|
|
101
|
+
.to(destination)
|
|
102
|
+
.contractSequenceId(contractSequenceId);
|
|
103
|
+
return await txBuilder.build();
|
|
104
|
+
};
|
|
105
|
+
it('should fail if the options object is missing parameters', async () => {
|
|
106
|
+
const explainParams = {
|
|
107
|
+
feeInfo: { fee: 1 },
|
|
108
|
+
txHex: null,
|
|
109
|
+
};
|
|
110
|
+
await basecoin.explainTransaction(explainParams).should.be.rejectedWith('missing explain tx parameters');
|
|
111
|
+
});
|
|
112
|
+
it('explain a transfer transaction', async () => {
|
|
113
|
+
const destination = '0xfaa8f14f46a99eb439c50e0c3b835cc21dad51b4';
|
|
114
|
+
const contractAddress = '0x9e2c5712ab4caf402a98c4bf58c79a0dfe718ad1';
|
|
115
|
+
const unsignedTransaction = await buildUnsignedTransaction({
|
|
116
|
+
destination,
|
|
117
|
+
contractAddress,
|
|
118
|
+
});
|
|
119
|
+
const explainParams = {
|
|
120
|
+
halfSigned: {
|
|
121
|
+
txHex: unsignedTransaction.toBroadcastFormat(),
|
|
122
|
+
},
|
|
123
|
+
feeInfo: { fee: 1 },
|
|
124
|
+
};
|
|
125
|
+
const explanation = await basecoin.explainTransaction(explainParams);
|
|
126
|
+
should.exist(explanation.id);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function runSignTransactionTests(coinName, builder, basecoin, testData) {
|
|
131
|
+
describe(`${coinName} sign transaction tests`, async () => {
|
|
132
|
+
const account_1 = {
|
|
133
|
+
address: '0x8Ce59c2d1702844F8EdED451AA103961bC37B4e8',
|
|
134
|
+
owner_1: '4ee089aceabf3ddbf748db79b1066c33b7d3ea1ab3eb7e325121bba2bff2f5ca',
|
|
135
|
+
owner_2: '5c7e4efff7304d4dfff6d5f1591844ec6f2adfa6a47e9fece6a3c1a4d755f1e3',
|
|
136
|
+
owner_3: '4421ab25dd91e1a3180d03d57c323a7886dcc313d3b3a4b4256a5791572bf597',
|
|
137
|
+
};
|
|
138
|
+
const account_2 = {
|
|
139
|
+
address: '0xeeaf0F05f37891ab4a21208B105A0687d12c5aF7',
|
|
140
|
+
owner_1: '4ee089aceabf3ddbf748db79b1066c33b7d3ea1ab3eb7e325121bba2bff2f5ca',
|
|
141
|
+
owner_2: '5ca116d25aec5f765465432cc421ff25ef9ffdc330b10bb3d9ad61e3baad88d7',
|
|
142
|
+
owner_3: '1fae946cc84af8bd74d610a88537e24e19c3349d478d86fc5bb59ba4c88fb9cc',
|
|
143
|
+
};
|
|
144
|
+
const coinTest = testData.COIN;
|
|
145
|
+
it('should sign an unsigned test tx', async () => {
|
|
146
|
+
builder.fee({
|
|
147
|
+
fee: '280000000000',
|
|
148
|
+
gasLimit: '7000000',
|
|
149
|
+
});
|
|
150
|
+
builder.counter(1);
|
|
151
|
+
builder.type(sdk_core_1.TransactionType.Send);
|
|
152
|
+
builder.contract(account_1.address);
|
|
153
|
+
const transferBuilder = builder.transfer();
|
|
154
|
+
transferBuilder.coin(coinTest).amount('1').to(account_2.address).expirationTime(10000).contractSequenceId(1);
|
|
155
|
+
const unsignedTx = await builder.build();
|
|
156
|
+
const unsignedTxForBroadcasting = unsignedTx.toBroadcastFormat();
|
|
157
|
+
const halfSignedRawTx = await basecoin.signTransaction({
|
|
158
|
+
txPrebuild: {
|
|
159
|
+
txHex: unsignedTxForBroadcasting,
|
|
160
|
+
},
|
|
161
|
+
prv: account_1.owner_2,
|
|
162
|
+
});
|
|
163
|
+
builder.transfer().key(account_1.owner_2);
|
|
164
|
+
const halfSignedTx = await builder.build();
|
|
165
|
+
const halfSignedTxForBroadcasting = halfSignedTx.toBroadcastFormat();
|
|
166
|
+
halfSignedRawTx.halfSigned.txHex.should.equals(halfSignedTxForBroadcasting);
|
|
167
|
+
halfSignedRawTx.halfSigned.recipients.length.should.equals(1);
|
|
168
|
+
halfSignedRawTx.halfSigned.recipients[0].address.toLowerCase().should.equals(account_2.address.toLowerCase());
|
|
169
|
+
halfSignedRawTx.halfSigned.recipients[0].amount.toLowerCase().should.equals('1');
|
|
170
|
+
});
|
|
171
|
+
it('should sign an unsigned test tx with eip1559', async () => {
|
|
172
|
+
builder.fee({
|
|
173
|
+
fee: '280000000000',
|
|
174
|
+
gasLimit: '7000000',
|
|
175
|
+
eip1559: {
|
|
176
|
+
maxFeePerGas: '7593123',
|
|
177
|
+
maxPriorityFeePerGas: '150',
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
builder.counter(1);
|
|
181
|
+
builder.type(sdk_core_1.TransactionType.Send);
|
|
182
|
+
builder.contract(account_1.address);
|
|
183
|
+
const transferBuilder = builder.transfer();
|
|
184
|
+
transferBuilder.coin(coinTest).amount('1').to(account_2.address).expirationTime(10000).contractSequenceId(1);
|
|
185
|
+
const unsignedTx = await builder.build();
|
|
186
|
+
const unsignedTxForBroadcasting = unsignedTx.toBroadcastFormat();
|
|
187
|
+
const halfSignedRawTx = await basecoin.signTransaction({
|
|
188
|
+
txPrebuild: {
|
|
189
|
+
txHex: unsignedTxForBroadcasting,
|
|
190
|
+
eip1559: {
|
|
191
|
+
maxFeePerGas: '7593123',
|
|
192
|
+
maxPriorityFeePerGas: '150',
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
prv: account_1.owner_2,
|
|
196
|
+
});
|
|
197
|
+
builder.transfer().key(account_1.owner_2);
|
|
198
|
+
const halfSignedTx = await builder.build();
|
|
199
|
+
const halfSignedTxForBroadcasting = halfSignedTx.toBroadcastFormat();
|
|
200
|
+
halfSignedRawTx.halfSigned.txHex.should.equals(halfSignedTxForBroadcasting);
|
|
201
|
+
halfSignedRawTx.halfSigned.recipients.length.should.equals(1);
|
|
202
|
+
halfSignedRawTx.halfSigned.recipients[0].address.toLowerCase().should.equals(account_2.address.toLowerCase());
|
|
203
|
+
halfSignedRawTx.halfSigned.recipients[0].amount.toLowerCase().should.equals('1');
|
|
204
|
+
halfSignedRawTx.halfSigned.eip1559.maxFeePerGas.should.equal('7593123');
|
|
205
|
+
halfSignedRawTx.halfSigned.eip1559.maxPriorityFeePerGas.should.equal('150');
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
function runTransactionVerificationTests(coinName, bitgo, basecoin, testData) {
|
|
210
|
+
describe(`${coinName} Transaction Verification`, () => {
|
|
211
|
+
const coinTest = testData.COIN;
|
|
212
|
+
const address1 = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
213
|
+
const address2 = '0x7e85bdc27c050e3905ebf4b8e634d9ad6edd0de6';
|
|
214
|
+
const hopDestinationAddress = '0x9c7e8ce6825bD48278B3Ab59228EE26f8BE7925b';
|
|
215
|
+
const hopTx = '0xf86b808504a817c8ff8252ff949c7e8ce6825bd48278b3ab59228ee26f8be7925b87038d7ea4c68000801ca011bc22c664570133dfca4f08a0b8d02339cf467046d6a4152f04f368d0eaf99ea01d6dc5cf0c897c8d4c3e1df53d0d042784c424536a4cc5b802552b7d64fee8b5';
|
|
216
|
+
const hopTxid = '0x4af65143bc77da2b50f35b3d13cacb4db18f026bf84bc0743550bc57b9b53351';
|
|
217
|
+
const userReqSig = '0x404db307f6147f0d8cd338c34c13906ef46a6faa7e0e119d5194ef05aec16e6f3d710f9b7901460f97e924066b62efd74443bd34402c6d40b49c203a559ff2c8';
|
|
218
|
+
const bitgoKeyXprv = 'xprv9s21ZrQH143K3tpWBHWe31sLoXNRQ9AvRYJgitkKxQ4ATFQMwvr7hHNqYRUnS7PsjzB7aK1VxqHLuNQjj1sckJ2Jwo2qxmsvejwECSpFMfC';
|
|
219
|
+
const bitgoKey = secp256k1_1.bip32.fromBase58(bitgoKeyXprv);
|
|
220
|
+
if (!bitgoKey.privateKey) {
|
|
221
|
+
throw new Error('no privateKey');
|
|
222
|
+
}
|
|
223
|
+
const hopTxBitgoSignature = '0xaa' +
|
|
224
|
+
Buffer.from(secp256k1.ecdsaSign(Buffer.from(hopTxid.slice(2), 'hex'), bitgoKey.privateKey).signature).toString('hex');
|
|
225
|
+
it('should verify a normal txPrebuild from the bitgo server that matches the client txParams', async () => {
|
|
226
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
227
|
+
const txParams = {
|
|
228
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
229
|
+
wallet: wallet,
|
|
230
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
231
|
+
};
|
|
232
|
+
const txPrebuild = {
|
|
233
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
234
|
+
nextContractSequenceId: 0,
|
|
235
|
+
gasPrice: 20000000000,
|
|
236
|
+
gasLimit: 500000,
|
|
237
|
+
isBatch: false,
|
|
238
|
+
coin: coinTest,
|
|
239
|
+
walletId: 'fakeWalletId',
|
|
240
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
241
|
+
};
|
|
242
|
+
const verification = {};
|
|
243
|
+
const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet, verification });
|
|
244
|
+
isTransactionVerified.should.equal(true);
|
|
245
|
+
});
|
|
246
|
+
it('should reject when client txParams are missing', async () => {
|
|
247
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
248
|
+
const txParams = null;
|
|
249
|
+
const txPrebuild = {
|
|
250
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
251
|
+
nextContractSequenceId: 0,
|
|
252
|
+
gasPrice: 20000000000,
|
|
253
|
+
gasLimit: 500000,
|
|
254
|
+
isBatch: false,
|
|
255
|
+
coin: coinTest,
|
|
256
|
+
walletId: 'fakeWalletId',
|
|
257
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
258
|
+
};
|
|
259
|
+
const verification = {};
|
|
260
|
+
await basecoin
|
|
261
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
262
|
+
.should.be.rejectedWith('missing params');
|
|
263
|
+
});
|
|
264
|
+
it('should reject txPrebuild that is both batch and hop', async () => {
|
|
265
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
266
|
+
const txParams = {
|
|
267
|
+
recipients: [
|
|
268
|
+
{ amount: '1000000000000', address: address1 },
|
|
269
|
+
{ amount: '2500000000000', address: address2 },
|
|
270
|
+
],
|
|
271
|
+
wallet: wallet,
|
|
272
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
273
|
+
hop: true,
|
|
274
|
+
};
|
|
275
|
+
const txPrebuild = {
|
|
276
|
+
recipients: [{ amount: '3500000000000', address: address1 }],
|
|
277
|
+
nextContractSequenceId: 0,
|
|
278
|
+
gasPrice: 20000000000,
|
|
279
|
+
gasLimit: 500000,
|
|
280
|
+
isBatch: true,
|
|
281
|
+
coin: coinTest,
|
|
282
|
+
walletId: 'fakeWalletId',
|
|
283
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
284
|
+
hopTransaction: {
|
|
285
|
+
tx: hopTx,
|
|
286
|
+
id: hopTxid,
|
|
287
|
+
signature: hopTxBitgoSignature,
|
|
288
|
+
paymentId: '2773928196',
|
|
289
|
+
gasPrice: 20000000000,
|
|
290
|
+
gasLimit: 500000,
|
|
291
|
+
amount: '1000000000000000',
|
|
292
|
+
recipient: hopDestinationAddress,
|
|
293
|
+
nonce: 0,
|
|
294
|
+
userReqSig: userReqSig,
|
|
295
|
+
gasPriceMax: 500000000000,
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
const verification = {};
|
|
299
|
+
await basecoin
|
|
300
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
301
|
+
.should.be.rejectedWith('tx cannot be both a batch and hop transaction');
|
|
302
|
+
});
|
|
303
|
+
it('should reject a txPrebuild with more than one recipient', async () => {
|
|
304
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
305
|
+
const txParams = {
|
|
306
|
+
recipients: [
|
|
307
|
+
{ amount: '1000000000000', address: address1 },
|
|
308
|
+
{ amount: '2500000000000', address: address2 },
|
|
309
|
+
],
|
|
310
|
+
wallet: wallet,
|
|
311
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
312
|
+
};
|
|
313
|
+
const txPrebuild = {
|
|
314
|
+
recipients: [
|
|
315
|
+
{ amount: '1000000000000', address: address1 },
|
|
316
|
+
{ amount: '2500000000000', address: address2 },
|
|
317
|
+
],
|
|
318
|
+
nextContractSequenceId: 0,
|
|
319
|
+
gasPrice: 20000000000,
|
|
320
|
+
gasLimit: 500000,
|
|
321
|
+
isBatch: true,
|
|
322
|
+
coin: coinTest,
|
|
323
|
+
walletId: 'fakeWalletId',
|
|
324
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
325
|
+
};
|
|
326
|
+
const verification = {};
|
|
327
|
+
await basecoin
|
|
328
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
329
|
+
.should.be.rejectedWith(`${coinTest} doesn't support sending to more than 1 destination address within a single transaction. Try again, using only a single recipient.`);
|
|
330
|
+
});
|
|
331
|
+
it('should reject a hop txPrebuild that does not send to its hop address', async () => {
|
|
332
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
333
|
+
const txParams = {
|
|
334
|
+
recipients: [{ amount: '1000000000000000', address: hopDestinationAddress }],
|
|
335
|
+
wallet: wallet,
|
|
336
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
337
|
+
hop: true,
|
|
338
|
+
};
|
|
339
|
+
const txPrebuild = {
|
|
340
|
+
recipients: [{ amount: '5000000000000000', address: address1 }],
|
|
341
|
+
nextContractSequenceId: 0,
|
|
342
|
+
gasPrice: 20000000000,
|
|
343
|
+
gasLimit: 500000,
|
|
344
|
+
isBatch: false,
|
|
345
|
+
coin: coinTest,
|
|
346
|
+
walletId: 'fakeWalletId',
|
|
347
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
348
|
+
hopTransaction: {
|
|
349
|
+
tx: hopTx,
|
|
350
|
+
id: hopTxid,
|
|
351
|
+
signature: hopTxBitgoSignature,
|
|
352
|
+
paymentId: '0',
|
|
353
|
+
gasPrice: 20000000000,
|
|
354
|
+
gasLimit: 500000,
|
|
355
|
+
amount: '1000000000000000',
|
|
356
|
+
recipient: hopDestinationAddress,
|
|
357
|
+
nonce: 0,
|
|
358
|
+
userReqSig: userReqSig,
|
|
359
|
+
gasPriceMax: 500000000000,
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
const verification = {};
|
|
363
|
+
await basecoin
|
|
364
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
365
|
+
.should.be.rejectedWith('recipient address of txPrebuild does not match hop address');
|
|
366
|
+
});
|
|
367
|
+
it('should reject a normal txPrebuild from the bitgo server with the wrong amount', async () => {
|
|
368
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
369
|
+
const txParams = {
|
|
370
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
371
|
+
wallet: wallet,
|
|
372
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
373
|
+
};
|
|
374
|
+
const txPrebuild = {
|
|
375
|
+
recipients: [{ amount: '2000000000000', address: address1 }],
|
|
376
|
+
nextContractSequenceId: 0,
|
|
377
|
+
gasPrice: 20000000000,
|
|
378
|
+
gasLimit: 500000,
|
|
379
|
+
isBatch: false,
|
|
380
|
+
coin: coinTest,
|
|
381
|
+
walletId: 'fakeWalletId',
|
|
382
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
383
|
+
};
|
|
384
|
+
const verification = {};
|
|
385
|
+
await basecoin
|
|
386
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
387
|
+
.should.be.rejectedWith('normal transaction amount in txPrebuild received from BitGo servers does not match txParams supplied by client');
|
|
388
|
+
});
|
|
389
|
+
it('should reject a normal txPrebuild from the bitgo server with the wrong recipient', async () => {
|
|
390
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
391
|
+
const txParams = {
|
|
392
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
393
|
+
wallet: wallet,
|
|
394
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
395
|
+
};
|
|
396
|
+
const txPrebuild = {
|
|
397
|
+
recipients: [{ amount: '1000000000000', address: address2 }],
|
|
398
|
+
nextContractSequenceId: 0,
|
|
399
|
+
gasPrice: 20000000000,
|
|
400
|
+
gasLimit: 500000,
|
|
401
|
+
isBatch: false,
|
|
402
|
+
coin: coinTest,
|
|
403
|
+
walletId: 'fakeWalletId',
|
|
404
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
405
|
+
};
|
|
406
|
+
const verification = {};
|
|
407
|
+
await basecoin
|
|
408
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
409
|
+
.should.be.rejectedWith('destination address in normal txPrebuild does not match that in txParams supplied by client');
|
|
410
|
+
});
|
|
411
|
+
it('should reject a txPrebuild from the bitgo server with the wrong coin', async () => {
|
|
412
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
413
|
+
const txParams = {
|
|
414
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
415
|
+
wallet: wallet,
|
|
416
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
417
|
+
};
|
|
418
|
+
const txPrebuild = {
|
|
419
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
420
|
+
nextContractSequenceId: 0,
|
|
421
|
+
gasPrice: 20000000000,
|
|
422
|
+
gasLimit: 500000,
|
|
423
|
+
isBatch: false,
|
|
424
|
+
coin: 'btc',
|
|
425
|
+
walletId: 'fakeWalletId',
|
|
426
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
427
|
+
};
|
|
428
|
+
const verification = {};
|
|
429
|
+
await basecoin
|
|
430
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
431
|
+
.should.be.rejectedWith('coin in txPrebuild did not match that in txParams supplied by client');
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
function runRecoveryTransactionTests(coinName, txBuilder, bitgo, testData, mockData) {
|
|
436
|
+
describe(`${coinName} Recover transaction:`, function () {
|
|
437
|
+
const baseUrl = testData.BASE_URL;
|
|
438
|
+
const userXpub = 'xpub661MyMwAqRbcEeTc8789MK5PUGEYiPG4F4V17n2Rd2LoTATA1XoCnJT5FAYAShQxSxtFjpo5NHmcWwTp2LiWGBMwpUcAA3HywhxivgYfq7q';
|
|
439
|
+
const userXprv = 'xprv9s21ZrQH143K2AP925b8zB8evEQ4JvYCsqZQKPcp4gopaN81TzUxEW8bPtVyDgjmddGhRRETn8xi1cVAB9bf1Bx9kGRRFgTZXxJayZLnag1';
|
|
440
|
+
const backupXpub = 'xpub661MyMwAqRbcFZX15xpZf4ERCGHiVSJm8r5C4yh1yXV2GrdZCUPYo4WQr6tN9oUywKXsgSHo7Risf9r22GH5joVD2hEEEhqnSCvK8qy11wW';
|
|
441
|
+
const backupXprv = 'xprv9s21ZrQH143K35SXywHZHvHgeETE5yaumd9bGbHQRBx3Q4JQew5JFGBvzqiZjCUkBdBUZnfuMDTGURRayN1hFSWxEJQsCEAMm1D3pk1h7Jj';
|
|
442
|
+
const coin = testData.COIN;
|
|
443
|
+
after(function () {
|
|
444
|
+
nock_1.default.cleanAll();
|
|
445
|
+
});
|
|
446
|
+
it('should generate an unsigned sweep', async () => {
|
|
447
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
448
|
+
const backupKeyAddress = '0x4f2c4830cc37f2785c646f89ded8a919219fa0e9';
|
|
449
|
+
(0, nock_1.default)(baseUrl)
|
|
450
|
+
.get('/api')
|
|
451
|
+
.twice()
|
|
452
|
+
.query(mockData.getTxListRequest(backupKeyAddress))
|
|
453
|
+
.reply(200, mockData.getTxListResponse);
|
|
454
|
+
(0, nock_1.default)(baseUrl)
|
|
455
|
+
.get('/api')
|
|
456
|
+
.query(mockData.getBalanceRequest(walletContractAddress))
|
|
457
|
+
.reply(200, mockData.getBalanceResponse);
|
|
458
|
+
(0, nock_1.default)(baseUrl)
|
|
459
|
+
.get('/api')
|
|
460
|
+
.query(mockData.getBalanceRequest(backupKeyAddress))
|
|
461
|
+
.reply(200, mockData.getBalanceResponse);
|
|
462
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
463
|
+
const basecoin = bitgo.coin(coin);
|
|
464
|
+
const transaction = (await basecoin.recover({
|
|
465
|
+
userKey: userXpub,
|
|
466
|
+
backupKey: backupXpub,
|
|
467
|
+
walletContractAddress: walletContractAddress,
|
|
468
|
+
recoveryDestination: sdk_test_1.TestBitGo.V2.TEST_ERC20_TOKEN_RECIPIENT,
|
|
469
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
470
|
+
gasLimit: 500000,
|
|
471
|
+
}));
|
|
472
|
+
should.exist(transaction);
|
|
473
|
+
transaction.should.have.property('txHex');
|
|
474
|
+
transaction.should.have.property('contractSequenceId');
|
|
475
|
+
transaction.should.have.property('expireTime');
|
|
476
|
+
transaction.should.have.property('gasLimit');
|
|
477
|
+
transaction.gasLimit.should.equal('500000');
|
|
478
|
+
transaction.should.have.property('walletContractAddress');
|
|
479
|
+
transaction.walletContractAddress.should.equal(sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS);
|
|
480
|
+
transaction.should.have.property('recipients');
|
|
481
|
+
const recipient = transaction.recipients[0];
|
|
482
|
+
recipient.should.have.property('address');
|
|
483
|
+
recipient.address.should.equal(sdk_test_1.TestBitGo.V2.TEST_ERC20_TOKEN_RECIPIENT);
|
|
484
|
+
recipient.should.have.property('amount');
|
|
485
|
+
recipient.amount.should.equal('9999999999999999928');
|
|
486
|
+
});
|
|
487
|
+
it('should construct a recovery transaction without BitGo', async () => {
|
|
488
|
+
const backupKeyAddress = '0x6d22efdd634996248170c948e5726007fc251bb3';
|
|
489
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
490
|
+
(0, nock_1.default)(baseUrl)
|
|
491
|
+
.get('/api')
|
|
492
|
+
.query(mockData.getTxListRequest(backupKeyAddress))
|
|
493
|
+
.reply(200, mockData.getTxListResponse);
|
|
494
|
+
(0, nock_1.default)(baseUrl)
|
|
495
|
+
.get('/api')
|
|
496
|
+
.query(mockData.getBalanceRequest(walletContractAddress))
|
|
497
|
+
.reply(200, mockData.getBalanceResponse);
|
|
498
|
+
(0, nock_1.default)(baseUrl)
|
|
499
|
+
.get('/api')
|
|
500
|
+
.query(mockData.getBalanceRequest(backupKeyAddress))
|
|
501
|
+
.reply(200, mockData.getBalanceResponse);
|
|
502
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
503
|
+
const basecoin = bitgo.coin(coin);
|
|
504
|
+
const transaction = (await basecoin.recover({
|
|
505
|
+
userKey: '{"iv":"VFZ3jvXhxo1Z+Yaf2MtZnA==","v":1,"iter":10000,"ks":256,"ts":64,"mode"\n' +
|
|
506
|
+
':"ccm","adata":"","cipher":"aes","salt":"p+fkHuLa/8k=","ct":"hYG7pvljLIgCjZ\n' +
|
|
507
|
+
'53PBlCde5KZRmlUKKHLtDMk+HJfuU46hW+x+C9WsIAO4gFPnTCvFVmQ8x7czCtcNFub5AO2otOG\n' +
|
|
508
|
+
'OsX4GE2gXOEmCl1TpWwwNhm7yMUjGJUpgW6ZZgXSXdDitSKi4V/hk78SGSzjFOBSPYRa6I="}\n',
|
|
509
|
+
backupKey: '{"iv":"AbsCtv1qwPIhOgyrCpNagA==","v":1,"iter":10000,"ks":256,"ts":64,"mode"\n' +
|
|
510
|
+
':"ccm","adata":"","cipher":"aes","salt":"5vpUDBUlzm8=","ct":"PapYYCjBXRLUKA\n' +
|
|
511
|
+
'JbOsB/EJ9B8fUmVQTxMPjUnQyAky12me9K66GiMEAxTD7kd6bYAQJuuTkATXKU7Bnf7vK9JxNOw\n' +
|
|
512
|
+
'oji7HF9eFH0aD4/hX5SWFfHF2Qfi+TnXv6hVsMAoisDZs3/F67/ZUaDYR0ZsdrQ4Q/cLD0="}\n',
|
|
513
|
+
walletContractAddress: walletContractAddress,
|
|
514
|
+
walletPassphrase: sdk_test_1.TestBitGo.V2.TEST_RECOVERY_PASSCODE,
|
|
515
|
+
recoveryDestination: sdk_test_1.TestBitGo.V2.TEST_ERC20_TOKEN_RECIPIENT,
|
|
516
|
+
gasLimit: 500000,
|
|
517
|
+
}));
|
|
518
|
+
should.exist(transaction);
|
|
519
|
+
transaction.should.have.property('tx');
|
|
520
|
+
transaction.should.have.property('id');
|
|
521
|
+
const decodedTx = src_1.optionalDeps.EthTx.Transaction.fromSerializedTx(src_1.optionalDeps.ethUtil.toBuffer(transaction.tx));
|
|
522
|
+
decodedTx.should.have.property('gasPrice');
|
|
523
|
+
decodedTx.should.have.property('nonce');
|
|
524
|
+
decodedTx.should.have.property('to');
|
|
525
|
+
});
|
|
526
|
+
it('should be able to second sign', async () => {
|
|
527
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
528
|
+
const backupKeyAddress = '0x4f2c4830cc37f2785c646f89ded8a919219fa0e9';
|
|
529
|
+
(0, nock_1.default)(baseUrl)
|
|
530
|
+
.get('/api')
|
|
531
|
+
.twice()
|
|
532
|
+
.query(mockData.getTxListRequest(backupKeyAddress))
|
|
533
|
+
.reply(200, mockData.getTxListResponse);
|
|
534
|
+
(0, nock_1.default)(baseUrl)
|
|
535
|
+
.get('/api')
|
|
536
|
+
.query(mockData.getBalanceRequest(walletContractAddress))
|
|
537
|
+
.reply(200, mockData.getBalanceResponse);
|
|
538
|
+
(0, nock_1.default)(baseUrl)
|
|
539
|
+
.get('/api')
|
|
540
|
+
.query(mockData.getBalanceRequest(backupKeyAddress))
|
|
541
|
+
.reply(200, mockData.getBalanceResponse);
|
|
542
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
543
|
+
const basecoin = bitgo.coin(coin);
|
|
544
|
+
const transaction = (await basecoin.recover({
|
|
545
|
+
userKey: userXpub,
|
|
546
|
+
backupKey: backupXpub,
|
|
547
|
+
walletContractAddress: walletContractAddress,
|
|
548
|
+
recoveryDestination: sdk_test_1.TestBitGo.V2.TEST_ERC20_TOKEN_RECIPIENT,
|
|
549
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
550
|
+
replayProtectionOptions: { chain: 80001, hardfork: 'london' },
|
|
551
|
+
gasLimit: 500000,
|
|
552
|
+
}));
|
|
553
|
+
const txPrebuild = {
|
|
554
|
+
txHex: transaction.txHex,
|
|
555
|
+
};
|
|
556
|
+
const params = {
|
|
557
|
+
txPrebuild,
|
|
558
|
+
prv: userXprv,
|
|
559
|
+
};
|
|
560
|
+
// sign transaction once
|
|
561
|
+
const halfSigned = await basecoin.signTransaction(params);
|
|
562
|
+
const halfSignedParams = {
|
|
563
|
+
txPrebuild: halfSigned,
|
|
564
|
+
isLastSignature: true,
|
|
565
|
+
walletContractAddress: walletContractAddress,
|
|
566
|
+
prv: backupXprv,
|
|
567
|
+
};
|
|
568
|
+
const finalSigned = (await basecoin.signTransaction(halfSignedParams));
|
|
569
|
+
finalSigned.should.have.property('txHex');
|
|
570
|
+
txBuilder.from(finalSigned.txHex);
|
|
571
|
+
const rebuiltTx = await txBuilder.build();
|
|
572
|
+
rebuiltTx.signature.length.should.equal(2);
|
|
573
|
+
rebuiltTx.outputs.length.should.equal(1);
|
|
574
|
+
});
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29pbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC9jb2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZ0JBLHNEQXdCQztBQUVELGdFQXFFQztBQUVELDBEQTBGQztBQUVELDBFQW9SQztBQUVELGtFQW1LQztBQXRvQkQsbURBQStEO0FBQy9ELHFEQUE4QztBQUM5QyxxREFBdUM7QUFDdkMsbURBQXVGO0FBQ3ZGLGdEQUF3QjtBQUN4QiwrQ0FBaUM7QUFDakMsbUNBTW1CO0FBRW5CLGNBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0FBRXhCLFNBQWdCLHFCQUFxQixDQUFDLFFBQWdCLEVBQUUsS0FBbUIsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFFBQWE7SUFDNUcsUUFBUSxDQUFDLEdBQUcsUUFBUSxrQkFBa0IsRUFBRSxHQUFHLEVBQUU7UUFDM0MsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQztRQUMvQixNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25DLEVBQUUsQ0FBQyxvQ0FBb0MsUUFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFO1lBQ3RELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFFbEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN2QyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN2QyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN4QyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLEtB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QUFDO1lBRTFCLE1BQU0sVUFBVSxHQUFHO2dCQUNqQixLQUFLLEVBQUUsV0FBVyxDQUFDLEtBQUs7YUFDekIsQ0FBQztZQUVGLE1BQU0sTUFBTSxHQUFHO2dCQUNiLFVBQVU7Z0JBQ1YsR0FBRyxFQUFFLFFBQVE7YUFDZCxDQUFDO1lBQ0Ysd0JBQXdCO1lBQ3hCLE1BQU0sVUFBVSxHQUFHLE1BQU0sUUFBUSxDQUFDLGVBQWUsQ0FBQyxNQUFnQyxDQUFDLENBQUM7WUFDcEYsTUFBTSxnQkFBZ0IsR0FBRztnQkFDdkIsVUFBVSxFQUFFLFVBQVU7Z0JBQ3RCLGVBQWUsRUFBRSxJQUFJO2dCQUNyQixxQkFBcUIsRUFBRSxxQkFBcUI7Z0JBQzVDLEdBQUcsRUFBRSxVQUFVO2FBQ2hCLENBQUM7WUFFRixNQUFNLFdBQVcsR0FBRyxDQUFDLE1BQU0sUUFBUSxDQUFDLGVBQWUsQ0FDakQsZ0JBQTBDLENBQzNDLENBQTJCLENBQUM7WUFDN0IsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2xDLE1BQU0sU0FBUyxHQUFHLE1BQU0sU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDM0MsU0FBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzQyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRlc3RCaXRHbywgVGVzdEJpdEdvQVBJIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLXRlc3QnO1xuaW1wb3J0IHsgYmlwMzIgfSBmcm9tICdAYml0Z28tYmV0YS9zZWNwMjU2azEnO1xuaW1wb3J0ICogYXMgc2VjcDI1NmsxIGZyb20gJ3NlY3AyNTZrMSc7XG5pbXBvcnQgeyBGdWxseVNpZ25lZFRyYW5zYWN0aW9uLCBUcmFuc2FjdGlvblR5cGUsIFdhbGxldCB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCBub2NrIGZyb20gJ25vY2snO1xuaW1wb3J0ICogYXMgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5pbXBvcnQge1xuICBPZmZsaW5lVmF1bHRUeEluZm8sXG4gIG9wdGlvbmFsRGVwcyxcbiAgU2lnblRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgVHJhbnNmZXJCdWlsZGVyLFxuICBUcmFuc2FjdGlvbkJ1aWxkZXIsXG59IGZyb20gJy4uLy4uL3NyYyc7XG5cbm5vY2suZW5hYmxlTmV0Q29ubmVjdCgpO1xuXG5leHBvcnQgZnVuY3Rpb24gcnVuQmFzaWNDb2luSW5mb1Rlc3RzKGNvaW5OYW1lOiBzdHJpbmcsIGJpdGdvOiBUZXN0Qml0R29BUEksIE1haW5Db2luLCBUZXN0Q29pbiwgdGVzdERhdGE6IGFueSkge1xuICBkZXNjcmliZShgJHtjb2luTmFtZX0gYmFzaWMgaW5mbyB0ZXN0YCwgKCkgPT4ge1xuICAgIGNvbnN0IGNvaW5UZXN0ID0gdGVzdERhdGEuQ09JTjtcbiAgICBjb25zdCBjb2luTWFpbiA9IGNvaW5UZXN0LnNsaWNlKDEpO1xuICAgIGl0KGBzaG91bGQgcmV0dXJuIHRoZSByaWdodCBpbmZvIGZvciAke2NvaW5NYWlufWAsICgpID0+IHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKGNvaW5NYWluKTtcblxuICAgICAgY29pbi5zaG91bGQuYmUuYW4uaW5zdGFuY2VvZihNYWluQ29pbik7XG4gICAgICBjb2luLmdldENoYWluKCkuc2hvdWxkLmVxdWFsKGNvaW5NYWluKTtcbiAgICAgIGNvaW4uZ2V0RmFtaWx5KCkuc2hvdWxkLmVxdWFsKGNvaW5NYWluKTtcbiAgICAgIGNvaW4uZ2V0RnVsbE5hbWUoKS5zaG91bGQuZXF1YWwodGVzdERhdGEuQ0hBSU5fRlVMTF9OQU1FKTtcbiAgICAgIGNvaW4uZ2V0QmFzZUZhY3RvcigpLnNob3VsZC5lcXVhbCgxZTE4KTtcbiAgICB9KTtcblxuICAgIGl0KGBzaG91bGQgcmV0dXJuIHRoZSByaWdodCBpbmZvIGZvciAke2NvaW5UZXN0fWAsICgpID0+IHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKGNvaW5UZXN0KTtcblxuICAgICAgY29pbi5zaG91bGQuYmUuYW4uaW5zdGFuY2VvZihUZXN0Q29pbik7XG4gICAgICBjb2luLmdldENoYWluKCkuc2hvdWxkLmVxdWFsKGNvaW5UZXN0KTtcbiAgICAgIGNvaW4uZ2V0RmFtaWx5KCkuc2hvdWxkLmVxdWFsKGNvaW5NYWluKTtcbiAgICAgIGNvaW4uZ2V0RnVsbE5hbWUoKS5zaG91bGQuZXF1YWwoYFRlc3RuZXQgJHt0ZXN0RGF0YS5DSEFJTl9GVUxMX05BTUV9YCk7XG4gICAgICBjb2luLmdldEJhc2VGYWN0b3IoKS5zaG91bGQuZXF1YWwoMWUxOCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcnVuRXhwbGFpblRyYW5zYWN0aW9uVGVzdHMoY29pbk5hbWU6IHN0cmluZywgdHhCdWlsZGVyOiBUcmFuc2FjdGlvbkJ1aWxkZXIsIGJhc2Vjb2luLCB0ZXN0RGF0YTogYW55KSB7XG4gIGRlc2NyaWJlKGAke2NvaW5OYW1lfSBleHBsYWluIHRyYW5zYWN0aW9uYCwgKCkgPT4ge1xuICAgIGNvbnN0IGNvaW5UZXN0ID0gdGVzdERhdGEuQ09JTjtcbiAgICAvKipcbiAgICAgKiBCdWlsZCBhbiB1bnNpZ25lZCBhY2NvdW50LWxpYiBtdWx0aS1zaWduYXR1cmUgc2VuZCB0cmFuc2FjdGlub1xuICAgICAqIEBwYXJhbSBkZXN0aW5hdGlvbiBUaGUgZGVzdGluYXRpb24gYWRkcmVzcyBvZiB0aGUgdHJhbnNhY3Rpb25cbiAgICAgKiBAcGFyYW0gY29udHJhY3RBZGRyZXNzIFRoZSBhZGRyZXNzIG9mIHRoZSBzbWFydCBjb250cmFjdCBwcm9jZXNzaW5nIHRoZSB0cmFuc2FjdGlvblxuICAgICAqIEBwYXJhbSBjb250cmFjdFNlcXVlbmNlSWQgVGhlIHNlcXVlbmNlIGlkIG9mIHRoZSBjb250cmFjdFxuICAgICAqIEBwYXJhbSBub25jZSBUaGUgbm9uY2Ugb2YgdGhlIHNlbmRpbmcgYWRkcmVzc1xuICAgICAqIEBwYXJhbSBleHBpcmVUaW1lIFRoZSBleHBpcmUgdGltZSBvZiB0aGUgdHJhbnNhY3Rpb25cbiAgICAgKiBAcGFyYW0gYW1vdW50IFRoZSBhbW91bnQgdG8gc2VuZCB0byB0aGUgcmVjaXBpZW50XG4gICAgICogQHBhcmFtIGdhc1ByaWNlIFRoZSBnYXMgcHJpY2Ugb2YgdGhlIHRyYW5zYWN0aW9uXG4gICAgICogQHBhcmFtIGdhc0xpbWl0IFRoZSBnYXMgbGltaXQgb2YgdGhlIHRyYW5zYWN0aW9uXG4gICAgICovXG4gICAgY29uc3QgYnVpbGRVbnNpZ25lZFRyYW5zYWN0aW9uID0gYXN5bmMgZnVuY3Rpb24gKHtcbiAgICAgIGRlc3RpbmF0aW9uLFxuICAgICAgY29udHJhY3RBZGRyZXNzLFxuICAgICAgY29udHJhY3RTZXF1ZW5jZUlkID0gMSxcbiAgICAgIG5vbmNlID0gMCxcbiAgICAgIGV4cGlyZVRpbWUgPSBNYXRoLmZsb29yKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC8gMTAwMCksXG4gICAgICBhbW91bnQgPSAnMTAwMDAwJyxcbiAgICAgIGdhc1ByaWNlID0gJzEwMDAwJyxcbiAgICAgIGdhc0xpbWl0ID0gJzIwMDAwJyxcbiAgICB9KSB7XG4gICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICB0eEJ1aWxkZXIuZmVlKHtcbiAgICAgICAgZmVlOiBnYXNQcmljZSxcbiAgICAgICAgZ2FzTGltaXQ6IGdhc0xpbWl0LFxuICAgICAgfSk7XG4gICAgICB0eEJ1aWxkZXIuY291bnRlcihub25jZSk7XG4gICAgICB0eEJ1aWxkZXIuY29udHJhY3QoY29udHJhY3RBZGRyZXNzKTtcbiAgICAgIGNvbnN0IHRyYW5zZmVyQnVpbGRlciA9IHR4QnVpbGRlci50cmFuc2ZlcigpIGFzIFRyYW5zZmVyQnVpbGRlcjtcblxuICAgICAgdHJhbnNmZXJCdWlsZGVyXG4gICAgICAgIC5jb2luKGNvaW5UZXN0KVxuICAgICAgICAuZXhwaXJhdGlvblRpbWUoZXhwaXJlVGltZSlcbiAgICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAgIC50byhkZXN0aW5hdGlvbilcbiAgICAgICAgLmNvbnRyYWN0U2VxdWVuY2VJZChjb250cmFjdFNlcXVlbmNlSWQpO1xuXG4gICAgICByZXR1cm4gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgfTtcbiAgICBpdCgnc2hvdWxkIGZhaWwgaWYgdGhlIG9wdGlvbnMgb2JqZWN0IGlzIG1pc3NpbmcgcGFyYW1ldGVycycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGV4cGxhaW5QYXJhbXMgPSB7XG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAxIH0sXG4gICAgICAgIHR4SGV4OiBudWxsLFxuICAgICAgfTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbihleHBsYWluUGFyYW1zKS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIGV4cGxhaW4gdHggcGFyYW1ldGVycycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2V4cGxhaW4gYSB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGRlc3RpbmF0aW9uID0gJzB4ZmFhOGYxNGY0NmE5OWViNDM5YzUwZTBjM2I4MzVjYzIxZGFkNTFiNCc7XG4gICAgICBjb25zdCBjb250cmFjdEFkZHJlc3MgPSAnMHg5ZTJjNTcxMmFiNGNhZjQwMmE5OGM0YmY1OGM3OWEwZGZlNzE4YWQxJztcblxuICAgICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJ1aWxkVW5zaWduZWRUcmFuc2FjdGlvbih7XG4gICAgICAgIGRlc3RpbmF0aW9uLFxuICAgICAgICBjb250cmFjdEFkZHJlc3MsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgZXhwbGFpblBhcmFtcyA9IHtcbiAgICAgICAgaGFsZlNpZ25lZDoge1xuICAgICAgICAgIHR4SGV4OiB1bnNpZ25lZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgICAgIH0sXG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAxIH0sXG4gICAgICB9O1xuICAgICAgY29uc3QgZXhwbGFuYXRpb24gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oZXhwbGFpblBhcmFtcyk7XG4gICAgICBzaG91bGQuZXhpc3QoZXhwbGFuYXRpb24uaWQpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJ1blNpZ25UcmFuc2FjdGlvblRlc3RzKGNvaW5OYW1lOiBzdHJpbmcsIGJ1aWxkZXI6IFRyYW5zYWN0aW9uQnVpbGRlciwgYmFzZWNvaW4sIHRlc3REYXRhOiBhbnkpIHtcbiAgZGVzY3JpYmUoYCR7Y29pbk5hbWV9IHNpZ24gdHJhbnNhY3Rpb24gdGVzdHNgLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgYWNjb3VudF8xID0ge1xuICAgICAgYWRkcmVzczogJzB4OENlNTljMmQxNzAyODQ0RjhFZEVENDUxQUExMDM5NjFiQzM3QjRlOCcsXG4gICAgICBvd25lcl8xOiAnNGVlMDg5YWNlYWJmM2RkYmY3NDhkYjc5YjEwNjZjMzNiN2QzZWExYWIzZWI3ZTMyNTEyMWJiYTJiZmYyZjVjYScsXG4gICAgICBvd25lcl8yOiAnNWM3ZTRlZmZmNzMwNGQ0ZGZmZjZkNWYxNTkxODQ0ZWM2ZjJhZGZhNmE0N2U5ZmVjZTZhM2MxYTRkNzU1ZjFlMycsXG4gICAgICBvd25lcl8zOiAnNDQyMWFiMjVkZDkxZTFhMzE4MGQwM2Q1N2MzMjNhNzg4NmRjYzMxM2QzYjNhNGI0MjU2YTU3OTE1NzJiZjU5NycsXG4gICAgfTtcblxuICAgIGNvbnN0IGFjY291bnRfMiA9IHtcbiAgICAgIGFkZHJlc3M6ICcweGVlYWYwRjA1ZjM3ODkxYWI0YTIxMjA4QjEwNUEwNjg3ZDEyYzVhRjcnLFxuICAgICAgb3duZXJfMTogJzRlZTA4OWFjZWFiZjNkZGJmNzQ4ZGI3OWIxMDY2YzMzYjdkM2VhMWFiM2ViN2UzMjUxMjFiYmEyYmZmMmY1Y2EnLFxuICAgICAgb3duZXJfMjogJzVjYTExNmQyNWFlYzVmNzY1NDY1NDMyY2M0MjFmZjI1ZWY5ZmZkYzMzMGIxMGJiM2Q5YWQ2MWUzYmFhZDg4ZDcnLFxuICAgICAgb3duZXJfMzogJzFmYWU5NDZjYzg0YWY4YmQ3NGQ2MTBhODg1MzdlMjRlMTljMzM0OWQ0NzhkODZmYzViYjU5YmE0Yzg4ZmI5Y2MnLFxuICAgIH07XG5cbiAgICBjb25zdCBjb2luVGVzdCA9IHRlc3REYXRhLkNPSU47XG5cbiAgICBpdCgnc2hvdWxkIHNpZ24gYW4gdW5zaWduZWQgdGVzdCB0eCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGJ1aWxkZXIuZmVlKHtcbiAgICAgICAgZmVlOiAnMjgwMDAwMDAwMDAwJyxcbiAgICAgICAgZ2FzTGltaXQ6ICc3MDAwMDAwJyxcbiAgICAgIH0pO1xuICAgICAgYnVpbGRlci5jb3VudGVyKDEpO1xuICAgICAgYnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICAgIGJ1aWxkZXIuY29udHJhY3QoYWNjb3VudF8xLmFkZHJlc3MpO1xuICAgICAgY29uc3QgdHJhbnNmZXJCdWlsZGVyID0gYnVpbGRlci50cmFuc2ZlcigpIGFzIFRyYW5zZmVyQnVpbGRlcjtcbiAgICAgIHRyYW5zZmVyQnVpbGRlci5jb2luKGNvaW5UZXN0KS5hbW91bnQoJzEnKS50byhhY2NvdW50XzIuYWRkcmVzcykuZXhwaXJhdGlvblRpbWUoMTAwMDApLmNvbnRyYWN0U2VxdWVuY2VJZCgxKTtcblxuICAgICAgY29uc3QgdW5zaWduZWRUeCA9IGF3YWl0IGJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHhGb3JCcm9hZGNhc3RpbmcgPSB1bnNpZ25lZFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGNvbnN0IGhhbGZTaWduZWRSYXdUeCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogdW5zaWduZWRUeEZvckJyb2FkY2FzdGluZyxcbiAgICAgICAgfSxcbiAgICAgICAgcHJ2OiBhY2NvdW50XzEub3duZXJfMixcbiAgICAgIH0pO1xuXG4gICAgICBidWlsZGVyLnRyYW5zZmVyKCkua2V5KGFjY291bnRfMS5vd25lcl8yKTtcbiAgICAgIGNvbnN0IGhhbGZTaWduZWRUeCA9IGF3YWl0IGJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IGhhbGZTaWduZWRUeEZvckJyb2FkY2FzdGluZyA9IGhhbGZTaWduZWRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgICBoYWxmU2lnbmVkUmF3VHguaGFsZlNpZ25lZC50eEhleC5zaG91bGQuZXF1YWxzKGhhbGZTaWduZWRUeEZvckJyb2FkY2FzdGluZyk7XG4gICAgICBoYWxmU2lnbmVkUmF3VHguaGFsZlNpZ25lZC5yZWNpcGllbnRzLmxlbmd0aC5zaG91bGQuZXF1YWxzKDEpO1xuICAgICAgaGFsZlNpZ25lZFJhd1R4LmhhbGZTaWduZWQucmVjaXBpZW50c1swXS5hZGRyZXNzLnRvTG93ZXJDYXNlKCkuc2hvdWxkLmVxdWFscyhhY2NvdW50XzIuYWRkcmVzcy50b0xvd2VyQ2FzZSgpKTtcbiAgICAgIGhhbGZTaWduZWRSYXdUeC5oYWxmU2lnbmVkLnJlY2lwaWVudHNbMF0uYW1vdW50LnRvTG93ZXJDYXNlKCkuc2hvdWxkLmVxdWFscygnMScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzaWduIGFuIHVuc2lnbmVkIHRlc3QgdHggd2l0aCBlaXAxNTU5JywgYXN5bmMgKCkgPT4ge1xuICAgICAgYnVpbGRlci5mZWUoe1xuICAgICAgICBmZWU6ICcyODAwMDAwMDAwMDAnLFxuICAgICAgICBnYXNMaW1pdDogJzcwMDAwMDAnLFxuICAgICAgICBlaXAxNTU5OiB7XG4gICAgICAgICAgbWF4RmVlUGVyR2FzOiAnNzU5MzEyMycsXG4gICAgICAgICAgbWF4UHJpb3JpdHlGZWVQZXJHYXM6ICcxNTAnLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBidWlsZGVyLmNvdW50ZXIoMSk7XG4gICAgICBidWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuICAgICAgYnVpbGRlci5jb250cmFjdChhY2NvdW50XzEuYWRkcmVzcyk7XG4gICAgICBjb25zdCB0cmFuc2ZlckJ1aWxkZXIgPSBidWlsZGVyLnRyYW5zZmVyKCkgYXMgVHJhbnNmZXJCdWlsZGVyO1xuICAgICAgdHJhbnNmZXJCdWlsZGVyLmNvaW4oY29pblRlc3QpLmFtb3VudCgnMScpLnRvKGFjY291bnRfMi5hZGRyZXNzKS5leHBpcmF0aW9uVGltZSgxMDAwMCkuY29udHJhY3RTZXF1ZW5jZUlkKDEpO1xuXG4gICAgICBjb25zdCB1bnNpZ25lZFR4ID0gYXdhaXQgYnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdW5zaWduZWRUeEZvckJyb2FkY2FzdGluZyA9IHVuc2lnbmVkVHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgY29uc3QgaGFsZlNpZ25lZFJhd1R4ID0gYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiB1bnNpZ25lZFR4Rm9yQnJvYWRjYXN0aW5nLFxuICAgICAgICAgIGVpcDE1NTk6IHtcbiAgICAgICAgICAgIG1heEZlZVBlckdhczogJzc1OTMxMjMnLFxuICAgICAgICAgICAgbWF4UHJpb3JpdHlGZWVQZXJHYXM6ICcxNTAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHBydjogYWNjb3VudF8xLm93bmVyXzIsXG4gICAgICB9KTtcblxuICAgICAgYnVpbGRlci50cmFuc2ZlcigpLmtleShhY2NvdW50XzEub3duZXJfMik7XG4gICAgICBjb25zdCBoYWxmU2lnbmVkVHggPSBhd2FpdCBidWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCBoYWxmU2lnbmVkVHhGb3JCcm9hZGNhc3RpbmcgPSBoYWxmU2lnbmVkVHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgaGFsZlNpZ25lZFJhd1R4LmhhbGZTaWduZWQudHhIZXguc2hvdWxkLmVxdWFscyhoYWxmU2lnbmVkVHhGb3JCcm9hZGNhc3RpbmcpO1xuICAgICAgaGFsZlNpZ25lZFJhd1R4LmhhbGZTaWduZWQucmVjaXBpZW50cy5sZW5ndGguc2hvdWxkLmVxdWFscygxKTtcbiAgICAgIGhhbGZTaWduZWRSYXdUeC5oYWxmU2lnbmVkLnJlY2lwaWVudHNbMF0uYWRkcmVzcy50b0xvd2VyQ2FzZSgpLnNob3VsZC5lcXVhbHMoYWNjb3VudF8yLmFkZHJlc3MudG9Mb3dlckNhc2UoKSk7XG4gICAgICBoYWxmU2lnbmVkUmF3VHguaGFsZlNpZ25lZC5yZWNpcGllbnRzWzBdLmFtb3VudC50b0xvd2VyQ2FzZSgpLnNob3VsZC5lcXVhbHMoJzEnKTtcbiAgICAgIGhhbGZTaWduZWRSYXdUeC5oYWxmU2lnbmVkLmVpcDE1NTkubWF4RmVlUGVyR2FzLnNob3VsZC5lcXVhbCgnNzU5MzEyMycpO1xuICAgICAgaGFsZlNpZ25lZFJhd1R4LmhhbGZTaWduZWQuZWlwMTU1OS5tYXhQcmlvcml0eUZlZVBlckdhcy5zaG91bGQuZXF1YWwoJzE1MCcpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJ1blRyYW5zYWN0aW9uVmVyaWZpY2F0aW9uVGVzdHMoY29pbk5hbWU6IHN0cmluZywgYml0Z286IFRlc3RCaXRHb0FQSSwgYmFzZWNvaW4sIHRlc3REYXRhOiBhbnkpIHtcbiAgZGVzY3JpYmUoYCR7Y29pbk5hbWV9IFRyYW5zYWN0aW9uIFZlcmlmaWNhdGlvbmAsICgpID0+IHtcbiAgICBjb25zdCBjb2luVGVzdCA9IHRlc3REYXRhLkNPSU47XG4gICAgY29uc3QgYWRkcmVzczEgPSAnMHgxNzRjZmQ4MjNhZjhjZTI3ZWQwYWZlZTNmY2YzYzNiYTI1OTExNmJlJztcbiAgICBjb25zdCBhZGRyZXNzMiA9ICcweDdlODViZGMyN2MwNTBlMzkwNWViZjRiOGU2MzRkOWFkNmVkZDBkZTYnO1xuICAgIGNvbnN0IGhvcERlc3RpbmF0aW9uQWRkcmVzcyA9ICcweDljN2U4Y2U2ODI1YkQ0ODI3OEIzQWI1OTIyOEVFMjZmOEJFNzkyNWInO1xuICAgIGNvbnN0IGhvcFR4ID1cbiAgICAgICcweGY4NmI4MDg1MDRhODE3YzhmZjgyNTJmZjk0OWM3ZThjZTY4MjViZDQ4Mjc4YjNhYjU5MjI4ZWUyNmY4YmU3OTI1Yjg3MDM4ZDdlYTRjNjgwMDA4MDFjYTAxMWJjMjJjNjY0NTcwMTMzZGZjYTRmMDhhMGI4ZDAyMzM5Y2Y0NjcwNDZkNmE0MTUyZjA0ZjM2OGQwZWFmOTllYTAxZDZkYzVjZjBjODk3YzhkNGMzZTFkZjUzZDBkMDQyNzg0YzQyNDUzNmE0Y2M1YjgwMjU1MmI3ZDY0ZmVlOGI1JztcbiAgICBjb25zdCBob3BUeGlkID0gJzB4NGFmNjUxNDNiYzc3ZGEyYjUwZjM1YjNkMTNjYWNiNGRiMThmMDI2YmY4NGJjMDc0MzU1MGJjNTdiOWI1MzM1MSc7XG4gICAgY29uc3QgdXNlclJlcVNpZyA9XG4gICAgICAnMHg0MDRkYjMwN2Y2MTQ3ZjBkOGNkMzM4YzM0YzEzOTA2ZWY0NmE2ZmFhN2UwZTExOWQ1MTk0ZWYwNWFlYzE2ZTZmM2Q3MTBmOWI3OTAxNDYwZjk3ZTkyNDA2NmI2MmVmZDc0NDQzYmQzNDQwMmM2ZDQwYjQ5YzIwM2E1NTlmZjJjOCc7XG4gICAgY29uc3QgYml0Z29LZXlYcHJ2ID1cbiAgICAgICd4cHJ2OXMyMVpyUUgxNDNLM3RwV0JIV2UzMXNMb1hOUlE5QXZSWUpnaXRrS3hRNEFURlFNd3ZyN2hITnFZUlVuUzdQc2p6QjdhSzFWeHFITHVOUWpqMXNja0oySndvMnF4bXN2ZWp3RUNTcEZNZkMnO1xuICAgIGNvbnN0IGJpdGdvS2V5ID0gYmlwMzIuZnJvbUJhc2U1OChiaXRnb0tleVhwcnYpO1xuICAgIGlmICghYml0Z29LZXkucHJpdmF0ZUtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyBwcml2YXRlS2V5Jyk7XG4gICAgfVxuICAgIGNvbnN0IGhvcFR4Qml0Z29TaWduYXR1cmUgPVxuICAgICAgJzB4YWEnICtcbiAgICAgIEJ1ZmZlci5mcm9tKHNlY3AyNTZrMS5lY2RzYVNpZ24oQnVmZmVyLmZyb20oaG9wVHhpZC5zbGljZSgyKSwgJ2hleCcpLCBiaXRnb0tleS5wcml2YXRlS2V5KS5zaWduYXR1cmUpLnRvU3RyaW5nKFxuICAgICAgICAnaGV4J1xuICAgICAgKTtcbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBhIG5vcm1hbCB0eFByZWJ1aWxkIGZyb20gdGhlIGJpdGdvIHNlcnZlciB0aGF0IG1hdGNoZXMgdGhlIGNsaWVudCB0eFBhcmFtcycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfV0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICBjb2luOiBjb2luVGVzdCxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBjb25zdCBpc1RyYW5zYWN0aW9uVmVyaWZpZWQgPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB3YWxsZXQsIHZlcmlmaWNhdGlvbiB9KTtcbiAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCB3aGVuIGNsaWVudCB0eFBhcmFtcyBhcmUgbWlzc2luZycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbnVsbDtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICBjb2luOiBjb2luVGVzdCxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ21pc3NpbmcgcGFyYW1zJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCB0eFByZWJ1aWxkIHRoYXQgaXMgYm90aCBiYXRjaCBhbmQgaG9wJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9LFxuICAgICAgICAgIHsgYW1vdW50OiAnMjUwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MyIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgICBob3A6IHRydWUsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICczNTAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogdHJ1ZSxcbiAgICAgICAgY29pbjogY29pblRlc3QsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICAgIGhvcFRyYW5zYWN0aW9uOiB7XG4gICAgICAgICAgdHg6IGhvcFR4LFxuICAgICAgICAgIGlkOiBob3BUeGlkLFxuICAgICAgICAgIHNpZ25hdHVyZTogaG9wVHhCaXRnb1NpZ25hdHVyZSxcbiAgICAgICAgICBwYXltZW50SWQ6ICcyNzczOTI4MTk2JyxcbiAgICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgICBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAgICAgICByZWNpcGllbnQ6IGhvcERlc3RpbmF0aW9uQWRkcmVzcyxcbiAgICAgICAgICBub25jZTogMCxcbiAgICAgICAgICB1c2VyUmVxU2lnOiB1c2VyUmVxU2lnLFxuICAgICAgICAgIGdhc1ByaWNlTWF4OiA1MDAwMDAwMDAwMDAsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHdhbGxldCwgdmVyaWZpY2F0aW9uIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCd0eCBjYW5ub3QgYmUgYm90aCBhIGJhdGNoIGFuZCBob3AgdHJhbnNhY3Rpb24nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGEgdHhQcmVidWlsZCB3aXRoIG1vcmUgdGhhbiBvbmUgcmVjaXBpZW50JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9LFxuICAgICAgICAgIHsgYW1vdW50OiAnMjUwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MyIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHsgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH0sXG4gICAgICAgICAgeyBhbW91bnQ6ICcyNTAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczIgfSxcbiAgICAgICAgXSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiB0cnVlLFxuICAgICAgICBjb2luOiBjb2luVGVzdCxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgYCR7Y29pblRlc3R9IGRvZXNuJ3Qgc3VwcG9ydCBzZW5kaW5nIHRvIG1vcmUgdGhhbiAxIGRlc3RpbmF0aW9uIGFkZHJlc3Mgd2l0aGluIGEgc2luZ2xlIHRyYW5zYWN0aW9uLiBUcnkgYWdhaW4sIHVzaW5nIG9ubHkgYSBzaW5nbGUgcmVjaXBpZW50LmBcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGEgaG9wIHR4UHJlYnVpbGQgdGhhdCBkb2VzIG5vdCBzZW5kIHRvIGl0cyBob3AgYWRkcmVzcycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwJywgYWRkcmVzczogaG9wRGVzdGluYXRpb25BZGRyZXNzIH1dLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgICAgaG9wOiB0cnVlLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnNTAwMDAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICBjb2luOiBjb2luVGVzdCxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgICAgaG9wVHJhbnNhY3Rpb246IHtcbiAgICAgICAgICB0eDogaG9wVHgsXG4gICAgICAgICAgaWQ6IGhvcFR4aWQsXG4gICAgICAgICAgc2lnbmF0dXJlOiBob3BUeEJpdGdvU2lnbmF0dXJlLFxuICAgICAgICAgIHBheW1lbnRJZDogJzAnLFxuICAgICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAwMDAwMDAwMDAnLFxuICAgICAgICAgIHJlY2lwaWVudDogaG9wRGVzdGluYXRpb25BZGRyZXNzLFxuICAgICAgICAgIG5vbmNlOiAwLFxuICAgICAgICAgIHVzZXJSZXFTaWc6IHVzZXJSZXFTaWcsXG4gICAgICAgICAgZ2FzUHJpY2VNYXg6IDUwMDAwMDAwMDAwMCxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3JlY2lwaWVudCBhZGRyZXNzIG9mIHR4UHJlYnVpbGQgZG9lcyBub3QgbWF0Y2ggaG9wIGFkZHJlc3MnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGEgbm9ybWFsIHR4UHJlYnVpbGQgZnJvbSB0aGUgYml0Z28gc2VydmVyIHdpdGggdGhlIHdyb25nIGFtb3VudCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfV0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMjAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICBjb2luOiBjb2luVGVzdCxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgJ25vcm1hbCB0cmFuc2FjdGlvbiBhbW91bnQgaW4gdHhQcmVidWlsZCByZWNlaXZlZCBmcm9tIEJpdEdvIHNlcnZlcnMgZG9lcyBub3QgbWF0Y2ggdHhQYXJhbXMgc3VwcGxpZWQgYnkgY2xpZW50J1xuICAgICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYSBub3JtYWwgdHhQcmVidWlsZCBmcm9tIHRoZSBiaXRnbyBzZXJ2ZXIgd2l0aCB0aGUgd3JvbmcgcmVjaXBpZW50JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9XSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczIgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogZmFsc2UsXG4gICAgICAgIGNvaW46IGNvaW5UZXN0LFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB3YWxsZXQsIHZlcmlmaWNhdGlvbiB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAnZGVzdGluYXRpb24gYWRkcmVzcyBpbiBub3JtYWwgdHhQcmVidWlsZCBkb2VzIG5vdCBtYXRjaCB0aGF0IGluIHR4UGFyYW1zIHN1cHBsaWVkIGJ5IGNsaWVudCdcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGEgdHhQcmVidWlsZCBmcm9tIHRoZSBiaXRnbyBzZXJ2ZXIgd2l0aCB0aGUgd3JvbmcgY29pbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfV0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICBjb2luOiAnYnRjJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ2NvaW4gaW4gdHhQcmVidWlsZCBkaWQgbm90IG1hdGNoIHRoYXQgaW4gdHhQYXJhbXMgc3VwcGxpZWQgYnkgY2xpZW50Jyk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcnVuUmVjb3ZlcnlUcmFuc2FjdGlvblRlc3RzKFxuICBjb2luTmFtZTogc3RyaW5nLFxuICB0eEJ1aWxkZXI6IFRyYW5zYWN0aW9uQnVpbGRlcixcbiAgYml0Z286IFRlc3RCaXRHb0FQSSxcbiAgdGVzdERhdGE6IGFueSxcbiAgbW9ja0RhdGE6IGFueVxuKSB7XG4gIGRlc2NyaWJlKGAke2NvaW5OYW1lfSBSZWNvdmVyIHRyYW5zYWN0aW9uOmAsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBiYXNlVXJsID0gdGVzdERhdGEuQkFTRV9VUkw7XG4gICAgY29uc3QgdXNlclhwdWIgPVxuICAgICAgJ3hwdWI2NjFNeU13QXFSYmNFZVRjODc4OU1LNVBVR0VZaVBHNEY0VjE3bjJSZDJMb1RBVEExWG9DbkpUNUZBWUFTaFF4U3h0RmpwbzVOSG1jV3dUcDJMaVdHQk13cFVjQUEzSHl3aHhpdmdZZnE3cSc7XG4gICAgY29uc3QgdXNlclhwcnYgPVxuICAgICAgJ3hwcnY5czIxWnJRSDE0M0syQVA5MjViOHpCOGV2RVE0SnZZQ3NxWlFLUGNwNGdvcGFOODFUelV4RVc4YlB0VnlEZ2ptZGRHaFJSRVRuOHhpMWNWQUI5YmYxQng5a0dSUkZnVFpYeEpheVpMbmFnMSc7XG4gICAgY29uc3QgYmFja3VwWHB1YiA9XG4gICAgICAneHB1YjY2MU15TXdBcVJiY0ZaWDE1eHBaZjRFUkNHSGlWU0ptOHI1QzR5aDF5WFYyR3JkWkNVUFlvNFdRcjZ0TjlvVXl3S1hzZ1NIbzdSaXNmOXIyMkdINWpvVkQyaEVFRWhxblNDdks4cXkxMXdXJztcbiAgICBjb25zdCBiYWNrdXBYcHJ2ID1cbiAgICAgICd4cHJ2OXMyMVpyUUgxNDNLMzVTWHl3SFpIdkhnZUVURTV5YXVtZDliR2JIUVJCeDNRNEpRZXc1SkZHQnZ6cWlaakNVa0JkQlVabmZ1TURUR1VSUmF5TjFoRlNXeEVKUXNDRUFNbTFEM3BrMWg3SmonO1xuICAgIGNvbnN0IGNvaW4gPSB0ZXN0RGF0YS5DT0lOO1xuXG4gICAgYWZ0ZXIoZnVuY3Rpb24gKCkge1xuICAgICAgbm9jay5jbGVhbkFsbCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBhbiB1bnNpZ25lZCBzd2VlcCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHdhbGxldENvbnRyYWN0QWRkcmVzcyA9IFRlc3RCaXRHby5WMi5URVNUX0VUSF9XQUxMRVRfRklSU1RfQUREUkVTUyBhcyBzdHJpbmc7XG4gICAgICBjb25zdCBiYWNrdXBLZXlBZGRyZXNzID0gJzB4NGYyYzQ4MzBjYzM3ZjI3ODVjNjQ2Zjg5ZGVkOGE5MTkyMTlmYTBlOSc7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAudHdpY2UoKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0VHhMaXN0UmVxdWVzdChiYWNrdXBLZXlBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0VHhMaXN0UmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldEJhbGFuY2VSZXF1ZXN0KHdhbGxldENvbnRyYWN0QWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldEJhbGFuY2VSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3QoYmFja3VwS2V5QWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldEJhbGFuY2VSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpLmdldCgnL2FwaScpLnF1ZXJ5KG1vY2tEYXRhLmdldENvbnRyYWN0Q2FsbFJlcXVlc3QpLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVzcG9uc2UpO1xuICAgICAgY29uc3QgYmFzZWNvaW46IGFueSA9IGJpdGdvLmNvaW4oY29pbik7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IChhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogdXNlclhwdWIsXG4gICAgICAgIGJhY2t1cEtleTogYmFja3VwWHB1YixcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiB3YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IFRlc3RCaXRHby5WMi5URVNUX0VSQzIwX1RPS0VOX1JFQ0lQSUVOVCBhcyBzdHJpbmcsXG4gICAgICAgIGVpcDE1NTk6IHsgbWF4RmVlUGVyR2FzOiAyMDAwMDAwMDAwMCwgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwMDAwMDAwMDAwIH0sXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICB9KSkgYXMgT2ZmbGluZVZhdWx0VHhJbmZvO1xuICAgICAgc2hvdWxkLmV4aXN0KHRyYW5zYWN0aW9uKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eEhleCcpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2NvbnRyYWN0U2VxdWVuY2VJZCcpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2V4cGlyZVRpbWUnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdnYXNMaW1pdCcpO1xuICAgICAgdHJhbnNhY3Rpb24uZ2FzTGltaXQuc2hvdWxkLmVxdWFsKCc1MDAwMDAnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCd3YWxsZXRDb250cmFjdEFkZHJlc3MnKTtcbiAgICAgIHRyYW5zYWN0aW9uLndhbGxldENvbnRyYWN0QWRkcmVzcy5zaG91bGQuZXF1YWwoVGVzdEJpdEdvLlYyLlRFU1RfRVRIX1dBTExFVF9GSVJTVF9BRERSRVNTKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdyZWNpcGllbnRzJyk7XG4gICAgICBjb25zdCByZWNpcGllbnQgPSB0cmFuc2FjdGlvbi5yZWNpcGllbnRzWzBdO1xuICAgICAgcmVjaXBpZW50LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhZGRyZXNzJyk7XG4gICAgICByZWNpcGllbnQuYWRkcmVzcy5zaG91bGQuZXF1YWwoVGVzdEJpdEdvLlYyLlRFU1RfRVJDMjBfVE9LRU5fUkVDSVBJRU5UKTtcbiAgICAgIHJlY2lwaWVudC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYW1vdW50Jyk7XG4gICAgICByZWNpcGllbnQuYW1vdW50LnNob3VsZC5lcXVhbCgnOTk5OTk5OTk5OTk5OTk5OTkyOCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjb25zdHJ1Y3QgYSByZWNvdmVyeSB0cmFuc2FjdGlvbiB3aXRob3V0IEJpdEdvJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYmFja3VwS2V5QWRkcmVzcyA9ICcweDZkMjJlZmRkNjM0OTk2MjQ4MTcwYzk0OGU1NzI2MDA3ZmMyNTFiYjMnO1xuICAgICAgY29uc3Qgd2FsbGV0Q29udHJhY3RBZGRyZXNzID0gVGVzdEJpdEdvLlYyLlRFU1RfRVRIX1dBTExFVF9GSVJTVF9BRERSRVNTIGFzIHN0cmluZztcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRUeExpc3RSZXF1ZXN0KGJhY2t1cEtleUFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRUeExpc3RSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3Qod2FsbGV0Q29udHJhY3RBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRCYWxhbmNlUmVxdWVzdChiYWNrdXBLZXlBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybCkuZ2V0KCcvYXBpJykucXVlcnkobW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVxdWVzdCkucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXNwb25zZSk7XG4gICAgICBjb25zdCBiYXNlY29pbjogYW55ID0gYml0Z28uY29pbihjb2luKTtcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OlxuICAgICAgICAgICd7XCJpdlwiOlwiVkZaM2p2WGh4bzFaK1lhZjJNdFpuQT09XCIsXCJ2XCI6MSxcIml0ZXJcIjoxMDAwMCxcImtzXCI6MjU2LFwidHNcIjo2NCxcIm1vZGVcIlxcbicgK1xuICAgICAgICAgICc6XCJjY21cIixcImFkYXRhXCI6XCJcIixcImNpcGhlclwiOlwiYWVzXCIsXCJzYWx0XCI6XCJwK2ZrSHVMYS84az1cIixcImN0XCI6XCJoWUc3cHZsakxJZ0NqWlxcbicgK1xuICAgICAgICAgICc1M1BCbENkZTVLWlJtbFVLS0hMdERNaytISmZ1VTQ2aFcreCtDOVdzSUFPNGdGUG5UQ3ZGVm1ROHg3Y3pDdGNORnViNUFPMm90T0dcXG4nICtcbiAgICAgICAgICAnT3NYNEdFMmdYT0VtQ2wxVHBXd3dOaG03eU1VakdKVXBnVzZaWmdYU1hkRGl0U0tpNFYvaGs3OFNHU3pqRk9CU1BZUmE2ST1cIn1cXG4nLFxuICAgICAgICBiYWNrdXBLZXk6XG4gICAgICAgICAgJ3tcIml2XCI6XCJBYnNDdHYxcXdQSWhPZ3lyQ3BOYWdBPT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAwLFwia3NcIjoyNTYsXCJ0c1wiOjY0LFwibW9kZVwiXFxuJyArXG4gICAgICAgICAgJzpcImNjbVwiLFwiYWRhdGFcIjpcIlwiLFwiY2lwaGVyXCI6XCJhZXNcIixcInNhbHRcIjpcIjV2cFVEQlVsem04PVwiLFwiY3RcIjpcIlBhcFlZQ2pCWFJMVUtBXFxuJyArXG4gICAgICAgICAgJ0piT3NCL0VKOUI4ZlVtVlFUeE1QalVuUXlBa3kxMm1lOUs2NkdpTUVBeFREN2tkNmJZQVFKdXVUa0FUWEtVN0JuZjd2SzlKeE5Pd1xcbicgK1xuICAgICAgICAgICdvamk3SEY5ZUZIMGFENC9oWDVTV0ZmSEYyUWZpK1RuWHY2aFZzTUFvaXNEWnMzL0Y2Ny9aVWFEWVIwWnNkclE0US9jTEQwPVwifVxcbicsXG5cbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiB3YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IFRlc3RCaXRHby5WMi5URVNUX1JFQ09WRVJZX1BBU1NDT0RFLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBUZXN0Qml0R28uVjIuVEVTVF9FUkMyMF9UT0tFTl9SRUNJUElFTlQgYXMgc3RyaW5nLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgfSkpIGFzIE9mZmxpbmVWYXVsdFR4SW5mbztcbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbik7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHgnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdpZCcpO1xuICAgICAgY29uc3QgZGVjb2RlZFR4ID0gb3B0aW9uYWxEZXBzLkV0aFR4LlRyYW5zYWN0aW9uLmZyb21TZXJpYWxpemVkVHgob3B0aW9uYWxEZXBzLmV0aFV0aWwudG9CdWZmZXIodHJhbnNhY3Rpb24udHgpKTtcbiAgICAgIGRlY29kZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZ2FzUHJpY2UnKTtcbiAgICAgIGRlY29kZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbm9uY2UnKTtcbiAgICAgIGRlY29kZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndG8nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYmUgYWJsZSB0byBzZWNvbmQgc2lnbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHdhbGxldENvbnRyYWN0QWRkcmVzcyA9IFRlc3RCaXRHby5WMi5URVNUX0VUSF9XQUxMRVRfRklSU1RfQUREUkVTUyBhcyBzdHJpbmc7XG4gICAgICBjb25zdCBiYWNrdXBLZXlBZGRyZXNzID0gJzB4NGYyYzQ4MzBjYzM3ZjI3ODVjNjQ2Zjg5ZGVkOGE5MTkyMTlmYTBlOSc7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAudHdpY2UoKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0VHhMaXN0UmVxdWVzdChiYWNrdXBLZXlBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0VHhMaXN0UmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldEJhbGFuY2VSZXF1ZXN0KHdhbGxldENvbnRyYWN0QWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldEJhbGFuY2VSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3QoYmFja3VwS2V5QWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldEJhbGFuY2VSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpLmdldCgnL2FwaScpLnF1ZXJ5KG1vY2tEYXRhLmdldENvbnRyYWN0Q2FsbFJlcXVlc3QpLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVzcG9uc2UpO1xuICAgICAgY29uc3QgYmFzZWNvaW46IGFueSA9IGJpdGdvLmNvaW4oY29pbik7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IChhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogdXNlclhwdWIsXG4gICAgICAgIGJhY2t1cEtleTogYmFja3VwWHB1YixcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiB3YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IFRlc3RCaXRHby5WMi5URVNUX0VSQzIwX1RPS0VOX1JFQ0lQSUVOVCBhcyBzdHJpbmcsXG4gICAgICAgIGVpcDE1NTk6IHsgbWF4RmVlUGVyR2FzOiAyMDAwMDAwMDAwMCwgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwMDAwMDAwMDAwIH0sXG4gICAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiB7IGNoYWluOiA4MDAwMSwgaGFyZGZvcms6ICdsb25kb24nIH0sXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICB9KSkgYXMgT2ZmbGluZVZhdWx0VHhJbmZvO1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICB0eEhleDogdHJhbnNhY3Rpb24udHhIZXgsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHR4UHJlYnVpbGQsXG4gICAgICAgIHBydjogdXNlclhwcnYsXG4gICAgICB9O1xuICAgICAgLy8gc2lnbiB0cmFuc2FjdGlvbiBvbmNlXG4gICAgICBjb25zdCBoYWxmU2lnbmVkID0gYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKHBhcmFtcyBhcyBTaWduVHJhbnNhY3Rpb25PcHRpb25zKTtcbiAgICAgIGNvbnN0IGhhbGZTaWduZWRQYXJhbXMgPSB7XG4gICAgICAgIHR4UHJlYnVpbGQ6IGhhbGZTaWduZWQsXG4gICAgICAgIGlzTGFzdFNpZ25hdHVyZTogdHJ1ZSxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiB3YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICAgIHBydjogYmFja3VwWHBydixcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGZpbmFsU2lnbmVkID0gKGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbihcbiAgICAgICAgaGFsZlNpZ25lZFBhcmFtcyBhcyBTaWduVHJhbnNhY3Rpb25PcHRpb25zXG4gICAgICApKSBhcyBGdWxseVNpZ25lZFRyYW5zYWN0aW9uO1xuICAgICAgZmluYWxTaWduZWQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG4gICAgICB0eEJ1aWxkZXIuZnJvbShmaW5hbFNpZ25lZC50eEhleCk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC5zaWduYXR1cmUubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICAgIHJlYnVpbHRUeC5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgfSk7XG4gIH0pO1xufVxuIl19
|