@bitgo-beta/sdk-coin-trx 1.0.2-beta.232 → 1.0.2-beta.2321
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/dist/resources/protobuf/Contract.proto +32 -0
- package/dist/resources/protobuf/tron.d.ts +1478 -214
- package/dist/resources/protobuf/tron.js +6312 -2600
- package/dist/resources/protobuf/tron.proto +6 -0
- package/dist/src/index.js +6 -2
- package/dist/src/lib/accountCreateTxBuilder.d.ts +60 -0
- package/dist/src/lib/accountCreateTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/accountCreateTxBuilder.js +191 -0
- package/dist/src/lib/constants.d.ts +4 -0
- package/dist/src/lib/constants.d.ts.map +1 -0
- package/dist/src/lib/constants.js +7 -0
- package/dist/src/lib/contractCallBuilder.d.ts +1 -35
- package/dist/src/lib/contractCallBuilder.d.ts.map +1 -1
- package/dist/src/lib/contractCallBuilder.js +13 -76
- package/dist/src/lib/delegateResourceTxBuilder.d.ts +27 -0
- package/dist/src/lib/delegateResourceTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/delegateResourceTxBuilder.js +104 -0
- package/dist/src/lib/enum.d.ts +40 -1
- package/dist/src/lib/enum.d.ts.map +1 -1
- package/dist/src/lib/enum.js +44 -4
- package/dist/src/lib/freezeBalanceTxBuilder.d.ts +71 -0
- package/dist/src/lib/freezeBalanceTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/freezeBalanceTxBuilder.js +217 -0
- package/dist/src/lib/iface.d.ts +248 -2
- package/dist/src/lib/iface.d.ts.map +1 -1
- package/dist/src/lib/iface.js +1 -1
- package/dist/src/lib/index.js +23 -9
- package/dist/src/lib/keyPair.d.ts +0 -1
- package/dist/src/lib/keyPair.d.ts.map +1 -1
- package/dist/src/lib/keyPair.js +31 -18
- package/dist/src/lib/resourceManagementTxBuilder.d.ts +72 -0
- package/dist/src/lib/resourceManagementTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/resourceManagementTxBuilder.js +150 -0
- package/dist/src/lib/tokenTransferBuilder.d.ts +1 -1
- package/dist/src/lib/tokenTransferBuilder.d.ts.map +1 -1
- package/dist/src/lib/tokenTransferBuilder.js +5 -3
- package/dist/src/lib/transaction.d.ts +3 -0
- package/dist/src/lib/transaction.d.ts.map +1 -1
- package/dist/src/lib/transaction.js +115 -6
- package/dist/src/lib/transactionBuilder.d.ts +53 -6
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
- package/dist/src/lib/transactionBuilder.js +121 -22
- package/dist/src/lib/undelegateResourceTxBuilder.d.ts +27 -0
- package/dist/src/lib/undelegateResourceTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/undelegateResourceTxBuilder.js +104 -0
- package/dist/src/lib/unfreezeBalanceTxBuilder.d.ts +65 -0
- package/dist/src/lib/unfreezeBalanceTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/unfreezeBalanceTxBuilder.js +210 -0
- package/dist/src/lib/utils.d.ts +115 -8
- package/dist/src/lib/utils.d.ts.map +1 -1
- package/dist/src/lib/utils.js +534 -55
- package/dist/src/lib/voteWitnessTxBuilder.d.ts +62 -0
- package/dist/src/lib/voteWitnessTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/voteWitnessTxBuilder.js +219 -0
- package/dist/src/lib/withdrawBuilder.d.ts +49 -0
- package/dist/src/lib/withdrawBuilder.d.ts.map +1 -0
- package/dist/src/lib/withdrawBuilder.js +167 -0
- package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.d.ts +49 -0
- package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.js +167 -0
- package/dist/src/lib/wrappedBuilder.d.ts +67 -1
- package/dist/src/lib/wrappedBuilder.d.ts.map +1 -1
- package/dist/src/lib/wrappedBuilder.js +114 -4
- package/dist/src/trx.d.ts +146 -8
- package/dist/src/trx.d.ts.map +1 -1
- package/dist/src/trx.js +705 -160
- package/dist/src/trxToken.d.ts +2 -2
- package/dist/src/trxToken.d.ts.map +1 -1
- package/dist/src/trxToken.js +22 -7
- package/dist/test/fixtures.d.ts +40 -0
- package/dist/test/fixtures.d.ts.map +1 -0
- package/dist/test/fixtures.js +46 -0
- package/dist/test/resources.d.ts +614 -0
- package/dist/test/resources.d.ts.map +1 -0
- package/dist/test/resources.js +782 -0
- package/dist/test/unit/index.d.ts +2 -0
- package/dist/test/unit/index.d.ts.map +1 -0
- package/dist/test/unit/index.js +19 -0
- package/dist/test/unit/keyPair.d.ts +2 -0
- package/dist/test/unit/keyPair.d.ts.map +1 -0
- package/dist/test/unit/keyPair.js +163 -0
- package/dist/test/unit/transaction.d.ts +2 -0
- package/dist/test/unit/transaction.d.ts.map +1 -0
- package/dist/test/unit/transaction.js +38 -0
- package/dist/test/unit/transactionBuilder/accountCreateTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/accountCreateTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/accountCreateTxBuilder.js +248 -0
- package/dist/test/unit/transactionBuilder/contractCallBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/contractCallBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/contractCallBuilder.js +315 -0
- package/dist/test/unit/transactionBuilder/delegateResourceTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/delegateResourceTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/delegateResourceTxBuilder.js +339 -0
- package/dist/test/unit/transactionBuilder/freezeBalanceTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/freezeBalanceTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/freezeBalanceTxBuilder.js +365 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.js +87 -0
- package/dist/test/unit/transactionBuilder/undelegateResourceTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/undelegateResourceTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/undelegateResourceTxBuilder.js +339 -0
- package/dist/test/unit/transactionBuilder/unfreezeBalanceTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/unfreezeBalanceTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/unfreezeBalanceTxBuilder.js +336 -0
- package/dist/test/unit/transactionBuilder/voteWitnessTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/voteWitnessTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/voteWitnessTxBuilder.js +277 -0
- package/dist/test/unit/transactionBuilder/withdrawBalanceBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/withdrawBalanceBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/withdrawBalanceBuilder.js +213 -0
- package/dist/test/unit/transactionBuilder/withdrawExpireUnfreezeTxBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/withdrawExpireUnfreezeTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/withdrawExpireUnfreezeTxBuilder.js +213 -0
- package/dist/test/unit/transactionBuilder/wrappedBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/wrappedBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/wrappedBuilder.js +68 -0
- package/dist/test/unit/transactionBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder.js +178 -0
- package/dist/test/unit/trx.d.ts +2 -0
- package/dist/test/unit/trx.d.ts.map +1 -0
- package/dist/test/unit/trx.js +843 -0
- package/dist/test/unit/trxToken.d.ts +2 -0
- package/dist/test/unit/trxToken.d.ts.map +1 -0
- package/dist/test/unit/trxToken.js +152 -0
- package/dist/test/unit/util.d.ts +2 -0
- package/dist/test/unit/util.d.ts.map +1 -0
- package/dist/test/unit/util.js +156 -0
- package/dist/test/unit/verifyTransaction.d.ts +2 -0
- package/dist/test/unit/verifyTransaction.d.ts.map +1 -0
- package/dist/test/unit/verifyTransaction.js +695 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +22 -16
- package/.eslintignore +0 -5
- package/.mocharc.yml +0 -8
- package/CHANGELOG.md +0 -118
- package/resources/README.md +0 -31
- package/resources/protobuf/Contract.proto +0 -256
- package/resources/protobuf/Discover.proto +0 -44
- package/resources/protobuf/tron.d.ts +0 -11205
- package/resources/protobuf/tron.js +0 -33480
- package/resources/protobuf/tron.proto +0 -677
|
@@ -0,0 +1,843 @@
|
|
|
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
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
40
|
+
const node_test_1 = require("node:test");
|
|
41
|
+
const sdk_api_1 = require("@bitgo-beta/sdk-api");
|
|
42
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
43
|
+
const sdk_test_1 = require("@bitgo-beta/sdk-test");
|
|
44
|
+
const _ = __importStar(require("lodash"));
|
|
45
|
+
const nock_1 = __importDefault(require("nock"));
|
|
46
|
+
const src_1 = require("../../src");
|
|
47
|
+
const fixtures_1 = require("../fixtures");
|
|
48
|
+
const resources_1 = require("../resources");
|
|
49
|
+
(0, node_test_1.describe)('TRON:', function () {
|
|
50
|
+
const bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
|
|
51
|
+
bitgo.initializeTestVars();
|
|
52
|
+
bitgo.safeRegister('trx', src_1.Trx.createInstance);
|
|
53
|
+
bitgo.safeRegister('ttrx', src_1.Ttrx.createInstance);
|
|
54
|
+
let basecoin;
|
|
55
|
+
// Test data from wallet 693b011a3ec26986f569b02140c7627e
|
|
56
|
+
const testWalletData = {
|
|
57
|
+
rootAddress: 'TAf36b36eqoMCzJJm3jwSsP81UvkMxrPbi',
|
|
58
|
+
receiveAddress: 'TFaD6DeKFMcBuGuDD7LbbqxTnKunhXfdya',
|
|
59
|
+
receiveAddressIndex: 2,
|
|
60
|
+
keychains: [
|
|
61
|
+
{
|
|
62
|
+
id: '693b0110271fc3f5749754097793bb8d',
|
|
63
|
+
pub: 'xpub661MyMwAqRbcFsVAdZyN2m8p21WHXg8NRNkqKApyS5gwmFsPdRTrmHYCnzR9vYe8DQ4uWGCBcAAsWE3r97HsFS3K2faZ2ejXNhHxdEoAEWC',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: '693b011065b9c4674825ce1f849b7bef',
|
|
67
|
+
pub: 'xpub661MyMwAqRbcErKpZr9ztTFJk6fzXWatMFgRnpXfsjybWBfE9847EVGrHHBsGP8fcnzJmJuevAbPUEpjHTjEEWfYUWNMEDahvssQein848o',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: '693b01117c41846abb04818815b89b6c',
|
|
71
|
+
pub: 'xpub661MyMwAqRbcFqZd7XU9DFW4f29VJzQt7UCA51ypaWa5ymhQ2pRZDTgViw3vZ56PqZ8dj1cracN3fAWhaiG1QKj9mvyt9Cba4nM2tPibNKw',
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
(0, node_test_1.before)(function () {
|
|
76
|
+
basecoin = bitgo.coin('ttrx');
|
|
77
|
+
});
|
|
78
|
+
(0, node_test_1.it)('should instantiate the coin', function () {
|
|
79
|
+
const basecoin = bitgo.coin('trx');
|
|
80
|
+
node_assert_1.default.ok(basecoin instanceof src_1.Trx);
|
|
81
|
+
});
|
|
82
|
+
(0, node_test_1.it)('explain a txHex', async function () {
|
|
83
|
+
const txHex = JSON.stringify(fixtures_1.mockTx);
|
|
84
|
+
const explainParams = {
|
|
85
|
+
txHex,
|
|
86
|
+
feeInfo: { fee: 1 },
|
|
87
|
+
txID: fixtures_1.mockTx.txID,
|
|
88
|
+
};
|
|
89
|
+
const explanation = await basecoin.explainTransaction(explainParams);
|
|
90
|
+
const toAddress = src_1.Utils.getBase58AddressFromHex(fixtures_1.mockTx.raw_data.contract[0].parameter.value.to_address);
|
|
91
|
+
node_assert_1.default.equal(explanation.id, fixtures_1.mockTx.txID);
|
|
92
|
+
node_assert_1.default.equal(explanation.outputs.length, 1);
|
|
93
|
+
node_assert_1.default.equal(explanation.outputs[0].amount, '10');
|
|
94
|
+
node_assert_1.default.equal(explanation.outputs[0].address, toAddress);
|
|
95
|
+
node_assert_1.default.equal(explanation.outputAmount, '10');
|
|
96
|
+
node_assert_1.default.equal(explanation.changeAmount, '0');
|
|
97
|
+
node_assert_1.default.equal(explanation.changeOutputs.length, 0);
|
|
98
|
+
node_assert_1.default.equal(explanation.fee.fee, 1);
|
|
99
|
+
node_assert_1.default.equal(explanation.expiration, fixtures_1.mockTx.raw_data.expiration);
|
|
100
|
+
node_assert_1.default.equal(explanation.timestamp, fixtures_1.mockTx.raw_data.timestamp);
|
|
101
|
+
});
|
|
102
|
+
(0, node_test_1.it)('should check valid addresses', function () {
|
|
103
|
+
const badAddresses = [
|
|
104
|
+
'',
|
|
105
|
+
null,
|
|
106
|
+
'xxxx',
|
|
107
|
+
'YZ09fd-',
|
|
108
|
+
'412C2BA4A9FF6C53207DC5B686BFECF75EA7B805772', // 43 hex chars — too long
|
|
109
|
+
'412C2BA4A9FF6C53207DC5B686BFECF75EA7B80', // too short
|
|
110
|
+
'TBChwKYNaTo4a4N68Me1qEiiKsRDspXqLLZ', // invalid base58 checksum
|
|
111
|
+
'0x341qg3922b1', // non-hex
|
|
112
|
+
'96be113992bdc3be24c11f6017085b605d253649', // bare 20-byte — not an on-chain address form
|
|
113
|
+
];
|
|
114
|
+
// base58 and hex (0x / 41) are alternative encodings of the same address (COINS-1575)
|
|
115
|
+
const goodAddresses = [
|
|
116
|
+
'TBChwKYNaTo4a4N68Me1qEiiKsRDspXqLp',
|
|
117
|
+
'TPcf5jtYUhCN1X14tN577zF4NepbDZbxT7',
|
|
118
|
+
'0x96be113992bdc3be24c11f6017085b605d253649',
|
|
119
|
+
'41E0C0F581D7D02D40826C1C6CBEE71F625D6344D0',
|
|
120
|
+
'412C2BA4A9FF6C53207DC5B686BFECF75EA7B80577',
|
|
121
|
+
'418840E6C55B9ADA326D211D818C34A994AECED808',
|
|
122
|
+
'412A2B9F7641D0750C1E822D0E49EF765C8106524B',
|
|
123
|
+
'41A614F803B6FD780986A42C78EC9C7F77E6DED13C',
|
|
124
|
+
];
|
|
125
|
+
badAddresses.map((addr) => {
|
|
126
|
+
node_assert_1.default.equal(basecoin.isValidAddress(addr), false);
|
|
127
|
+
});
|
|
128
|
+
goodAddresses.map((addr) => {
|
|
129
|
+
node_assert_1.default.equal(basecoin.isValidAddress(addr), true);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
(0, node_test_1.it)('should canonicalize hex addresses to base58 (COINS-1575)', function () {
|
|
133
|
+
const base58 = 'TGai5uHgBcoLERrzDXMepqZB8Et7D8nV8K';
|
|
134
|
+
const hex41 = '414887974f42a789ef6d4dfc7ba28b1583219434b3';
|
|
135
|
+
const hex0x = '0x4887974f42a789ef6d4dfc7ba28b1583219434b3';
|
|
136
|
+
node_assert_1.default.equal(basecoin.canonicalAddress(base58), base58);
|
|
137
|
+
node_assert_1.default.equal(basecoin.canonicalAddress(hex41), base58);
|
|
138
|
+
node_assert_1.default.equal(basecoin.canonicalAddress(hex0x), base58);
|
|
139
|
+
node_assert_1.default.equal(basecoin.canonicalAddress('not-an-address'), 'not-an-address');
|
|
140
|
+
});
|
|
141
|
+
(0, node_test_1.it)('should reject hex forms in strict Base58 mode', function () {
|
|
142
|
+
const base58 = 'TGai5uHgBcoLERrzDXMepqZB8Et7D8nV8K';
|
|
143
|
+
const hex41 = '414887974f42a789ef6d4dfc7ba28b1583219434b3';
|
|
144
|
+
const hex0x = '0x4887974f42a789ef6d4dfc7ba28b1583219434b3';
|
|
145
|
+
// default behavior unchanged: all three forms accepted
|
|
146
|
+
node_assert_1.default.equal(basecoin.isValidAddress(base58), true);
|
|
147
|
+
node_assert_1.default.equal(basecoin.isValidAddress(hex41), true);
|
|
148
|
+
node_assert_1.default.equal(basecoin.isValidAddress(hex0x), true);
|
|
149
|
+
// strictBase58: only canonical Base58 accepted
|
|
150
|
+
node_assert_1.default.equal(basecoin.isValidAddress(base58, { strictBase58: true }), true);
|
|
151
|
+
node_assert_1.default.equal(basecoin.isValidAddress(hex41, { strictBase58: true }), false);
|
|
152
|
+
node_assert_1.default.equal(basecoin.isValidAddress(hex0x, { strictBase58: true }), false);
|
|
153
|
+
node_assert_1.default.equal(basecoin.isValidAddress('', { strictBase58: true }), false);
|
|
154
|
+
node_assert_1.default.equal(basecoin.isValidAddress('TBChwKYNaTo4a4N68Me1qEiiKsRDspXqLLZ', { strictBase58: true }), false);
|
|
155
|
+
// explicit false keeps lenient behavior
|
|
156
|
+
node_assert_1.default.equal(basecoin.isValidAddress(hex0x, { strictBase58: false }), true);
|
|
157
|
+
});
|
|
158
|
+
(0, node_test_1.it)('should throw if the params object is missing parameters', async function () {
|
|
159
|
+
const explainParams = {
|
|
160
|
+
feeInfo: { fee: 1 },
|
|
161
|
+
txID: fixtures_1.mockTx.txID,
|
|
162
|
+
txHex: null,
|
|
163
|
+
};
|
|
164
|
+
await node_assert_1.default.rejects(basecoin.explainTransaction(explainParams), {
|
|
165
|
+
message: 'missing explain tx parameters',
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
(0, node_test_1.it)('explain an half-signed/fully signed transaction', async function () {
|
|
169
|
+
const txHex = JSON.stringify(fixtures_1.mockTx);
|
|
170
|
+
const explainParams = {
|
|
171
|
+
halfSigned: { txHex },
|
|
172
|
+
feeInfo: { fee: 1 },
|
|
173
|
+
txID: fixtures_1.mockTx.txID,
|
|
174
|
+
};
|
|
175
|
+
const explanation = await basecoin.explainTransaction(explainParams);
|
|
176
|
+
const toAddress = src_1.Utils.getBase58AddressFromHex(fixtures_1.mockTx.raw_data.contract[0].parameter.value.to_address);
|
|
177
|
+
node_assert_1.default.equal(explanation.id, fixtures_1.mockTx.txID);
|
|
178
|
+
node_assert_1.default.equal(explanation.outputs.length, 1);
|
|
179
|
+
node_assert_1.default.equal(explanation.outputs[0].amount, '10');
|
|
180
|
+
node_assert_1.default.equal(explanation.outputs[0].address, toAddress);
|
|
181
|
+
node_assert_1.default.equal(explanation.outputAmount, '10');
|
|
182
|
+
node_assert_1.default.equal(explanation.changeAmount, '0');
|
|
183
|
+
node_assert_1.default.equal(explanation.changeOutputs.length, 0);
|
|
184
|
+
node_assert_1.default.equal(explanation.fee.fee, 1);
|
|
185
|
+
node_assert_1.default.equal(explanation.expiration, fixtures_1.mockTx.raw_data.expiration);
|
|
186
|
+
node_assert_1.default.equal(explanation.timestamp, fixtures_1.mockTx.raw_data.timestamp);
|
|
187
|
+
});
|
|
188
|
+
(0, node_test_1.it)('should sign a half signed tx', async function () {
|
|
189
|
+
const tx = await basecoin.signTransaction(fixtures_1.signTxOptions);
|
|
190
|
+
const unsignedTxJson = JSON.parse(fixtures_1.signTxOptions.txPrebuild.txHex);
|
|
191
|
+
const signedTxJson = JSON.parse(tx.halfSigned.txHex);
|
|
192
|
+
node_assert_1.default.equal(signedTxJson.txID, unsignedTxJson.txID);
|
|
193
|
+
node_assert_1.default.equal(signedTxJson.raw_data_hex, unsignedTxJson.raw_data_hex);
|
|
194
|
+
node_assert_1.default.deepStrictEqual(JSON.stringify(signedTxJson.raw_data), JSON.stringify(unsignedTxJson.raw_data));
|
|
195
|
+
node_assert_1.default.equal(signedTxJson.signature.length, 1);
|
|
196
|
+
node_assert_1.default.equal(signedTxJson.signature[0], '0a9944316924ec7fba4895f1ea1e7cc95f9e2b828ae268a48a8dbeddef40c6f5e127170a95aed9f3f5425b13058d0cb6ef1f5c2213190e482e87043691f22e6800');
|
|
197
|
+
});
|
|
198
|
+
(0, node_test_1.it)('should sign with an Xprv a half signed tx', async function () {
|
|
199
|
+
const p = {
|
|
200
|
+
prv: 'xprv9s21ZrQH143K2sg2Cukk5XqLQdrYnMCDah3y1FFVy6Hz9bQfqMSfmUiHPVHKhcUyft3N1emE5FudJVxgFm5N12MAg5o7DTPsDATTkwNgr73',
|
|
201
|
+
txPrebuild: {
|
|
202
|
+
txHex: fixtures_1.signTxOptions.txPrebuild.txHex,
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
const tx = await basecoin.signTransaction(p);
|
|
206
|
+
const unsignedTxJson = JSON.parse(fixtures_1.signTxOptions.txPrebuild.txHex);
|
|
207
|
+
const signedTxJson = JSON.parse(tx.halfSigned.txHex);
|
|
208
|
+
node_assert_1.default.equal(signedTxJson.txID, unsignedTxJson.txID);
|
|
209
|
+
node_assert_1.default.equal(signedTxJson.raw_data_hex, unsignedTxJson.raw_data_hex);
|
|
210
|
+
node_assert_1.default.deepStrictEqual(JSON.stringify(signedTxJson.raw_data), JSON.stringify(unsignedTxJson.raw_data));
|
|
211
|
+
node_assert_1.default.equal(signedTxJson.signature.length, 1);
|
|
212
|
+
node_assert_1.default.equal(signedTxJson.signature[0], '65e56f53a458c6f82d1ef39b2cf5be685a906ad22bb02699f907fcb72ef26f1e91cfc2b6a43bf5432faa0b63bdc5aebf1dc2f49a675d28d23fd7e038b3358b0600');
|
|
213
|
+
});
|
|
214
|
+
(0, node_test_1.it)('should add feeLimit to recipient', async function () {
|
|
215
|
+
const feeLimit = 100;
|
|
216
|
+
const buildParams = {
|
|
217
|
+
recipients: [{ data: 'test' }],
|
|
218
|
+
feeLimit,
|
|
219
|
+
};
|
|
220
|
+
basecoin.getExtraPrebuildParams(buildParams);
|
|
221
|
+
node_assert_1.default.equal(buildParams.recipients[0].feeLimit, feeLimit);
|
|
222
|
+
});
|
|
223
|
+
(0, node_test_1.it)('should`t add any new field', async function () {
|
|
224
|
+
const buildParams = {
|
|
225
|
+
recipients: [{ data: 'test' }],
|
|
226
|
+
};
|
|
227
|
+
const unmodifiedBuildParams = _.cloneDeep(buildParams);
|
|
228
|
+
await basecoin.getExtraPrebuildParams(buildParams);
|
|
229
|
+
node_assert_1.default.deepStrictEqual(buildParams, unmodifiedBuildParams);
|
|
230
|
+
});
|
|
231
|
+
(0, node_test_1.describe)('Keypairs:', () => {
|
|
232
|
+
(0, node_test_1.it)('should generate a keypair from random seed', function () {
|
|
233
|
+
const keyPair = basecoin.generateKeyPair();
|
|
234
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(keyPair, 'pub'));
|
|
235
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(keyPair, 'prv'));
|
|
236
|
+
node_assert_1.default.equal(basecoin.isValidPub(keyPair.pub), true);
|
|
237
|
+
});
|
|
238
|
+
(0, node_test_1.it)('should generate a keypair from a seed', function () {
|
|
239
|
+
const seedText = '80350b4208d381fbfe2276a326603049fe500731c46d3c9936b5ce036b51377f24bab7dd0c2af7f107416ef858ff79b0670c72406dad064e72bb17fc0a9038bb';
|
|
240
|
+
const seed = Buffer.from(seedText, 'hex');
|
|
241
|
+
const keyPair = basecoin.generateKeyPair(seed);
|
|
242
|
+
node_assert_1.default.equal(keyPair.pub, 'xpub661MyMwAqRbcFAwqvSGbk35kJf7CQqdN1w4CMUBBTqH5e3ivjU6D8ugv9hRSgRbRenC4w3ahXdLVahwjgjXhSuQKMdNdn55Y9TNSagBktws');
|
|
243
|
+
node_assert_1.default.equal(keyPair.prv, 'xprv9s21ZrQH143K2gsNpQjbNu91kdGi1NuWei8bZ5mZuVk6mFPnBvmxb7NSJQdbZW3FGpK3Ycn7jorAXcEzMvviGtbyBz5tBrjfnWyQp3g75FK');
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
(0, node_test_1.describe)('Build Unsigned Sweep', () => {
|
|
247
|
+
(0, node_test_1.afterEach)(() => {
|
|
248
|
+
node_test_1.mock.reset();
|
|
249
|
+
});
|
|
250
|
+
(0, node_test_1.it)('should recover trx from base address to recovery address', async function () {
|
|
251
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', (...args) => {
|
|
252
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.baseAddress) {
|
|
253
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(3000000));
|
|
254
|
+
}
|
|
255
|
+
return undefined;
|
|
256
|
+
});
|
|
257
|
+
const baseAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.baseAddress);
|
|
258
|
+
const destinationHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.recoveryDestination);
|
|
259
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getBuildTransaction', (...args) => {
|
|
260
|
+
if (args.length > 0 && args[0] === destinationHex && args[1] === baseAddrHex && args[2] === 900000) {
|
|
261
|
+
return Promise.resolve((0, resources_1.creationTransaction)(baseAddrHex, destinationHex, 900000));
|
|
262
|
+
}
|
|
263
|
+
return undefined;
|
|
264
|
+
});
|
|
265
|
+
const res = await basecoin.recover({
|
|
266
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
267
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
268
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
269
|
+
recoveryDestination: resources_1.TestRecoverData.recoveryDestination,
|
|
270
|
+
});
|
|
271
|
+
node_assert_1.default.notEqual(res.length, 0);
|
|
272
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'txHex'));
|
|
273
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'feeInfo'));
|
|
274
|
+
const rawData = JSON.parse(res.txHex).raw_data;
|
|
275
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(rawData, 'contract'));
|
|
276
|
+
const value = rawData.contract[0].parameter.value;
|
|
277
|
+
node_assert_1.default.equal(value.amount, 900000);
|
|
278
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.owner_address), resources_1.TestRecoverData.baseAddress);
|
|
279
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.to_address), resources_1.TestRecoverData.recoveryDestination);
|
|
280
|
+
});
|
|
281
|
+
(0, node_test_1.it)('should recover trx from base address to recovery address with scan passed as valid integer string', async function () {
|
|
282
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', (...args) => {
|
|
283
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.baseAddress) {
|
|
284
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(3000000));
|
|
285
|
+
}
|
|
286
|
+
return undefined;
|
|
287
|
+
});
|
|
288
|
+
const baseAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.baseAddress);
|
|
289
|
+
const destinationHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.recoveryDestination);
|
|
290
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getBuildTransaction', (...args) => {
|
|
291
|
+
if (args.length > 0 && args[0] === destinationHex && args[1] === baseAddrHex && args[2] === 900000) {
|
|
292
|
+
return Promise.resolve((0, resources_1.creationTransaction)(baseAddrHex, destinationHex, 900000));
|
|
293
|
+
}
|
|
294
|
+
return undefined;
|
|
295
|
+
});
|
|
296
|
+
const res = await basecoin.recover({
|
|
297
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
298
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
299
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
300
|
+
recoveryDestination: resources_1.TestRecoverData.recoveryDestination,
|
|
301
|
+
scan: '10',
|
|
302
|
+
});
|
|
303
|
+
node_assert_1.default.notEqual(res.length, 0);
|
|
304
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'txHex'));
|
|
305
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'feeInfo'));
|
|
306
|
+
const rawData = JSON.parse(res.txHex).raw_data;
|
|
307
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(rawData, 'contract'));
|
|
308
|
+
const value = rawData.contract[0].parameter.value;
|
|
309
|
+
node_assert_1.default.equal(value.amount, 900000);
|
|
310
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.owner_address), resources_1.TestRecoverData.baseAddress);
|
|
311
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.to_address), resources_1.TestRecoverData.recoveryDestination);
|
|
312
|
+
});
|
|
313
|
+
(0, node_test_1.it)('should fail recover trx from base address to recovery address with scan passed as valid integer string', async function () {
|
|
314
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', (...args) => {
|
|
315
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.baseAddress) {
|
|
316
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(3000000));
|
|
317
|
+
}
|
|
318
|
+
return undefined;
|
|
319
|
+
});
|
|
320
|
+
const baseAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.baseAddress);
|
|
321
|
+
const destinationHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.recoveryDestination);
|
|
322
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getBuildTransaction', (...args) => {
|
|
323
|
+
if (args.length > 0 && args[0] === destinationHex && args[1] === baseAddrHex && args[2] === 900000) {
|
|
324
|
+
return Promise.resolve((0, resources_1.creationTransaction)(baseAddrHex, destinationHex, 900000));
|
|
325
|
+
}
|
|
326
|
+
return undefined;
|
|
327
|
+
});
|
|
328
|
+
await node_assert_1.default.rejects(basecoin.recover({
|
|
329
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
330
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
331
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
332
|
+
recoveryDestination: resources_1.TestRecoverData.recoveryDestination,
|
|
333
|
+
scan: 'abc',
|
|
334
|
+
}), {
|
|
335
|
+
message: 'Invalid scanning factor',
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
(0, node_test_1.it)('should recover trx from receive address to base address', async function () {
|
|
339
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', (...args) => {
|
|
340
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.baseAddress) {
|
|
341
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(2000000));
|
|
342
|
+
}
|
|
343
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.firstReceiveAddress) {
|
|
344
|
+
return Promise.resolve((0, resources_1.receiveAddressBalance)(102100000, resources_1.TestRecoverData.firstReceiveAddress));
|
|
345
|
+
}
|
|
346
|
+
return undefined;
|
|
347
|
+
});
|
|
348
|
+
const firstReceiveAddressHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.firstReceiveAddress);
|
|
349
|
+
const baseAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.baseAddress);
|
|
350
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getBuildTransaction', (...args) => {
|
|
351
|
+
if (args.length > 0 && args[0] === baseAddrHex && args[1] === firstReceiveAddressHex && args[2] === 100000000) {
|
|
352
|
+
return Promise.resolve((0, resources_1.creationTransaction)(firstReceiveAddressHex, baseAddrHex, 100000000));
|
|
353
|
+
}
|
|
354
|
+
return undefined;
|
|
355
|
+
});
|
|
356
|
+
const res = await basecoin.recover({
|
|
357
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
358
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
359
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
360
|
+
recoveryDestination: resources_1.TestRecoverData.recoveryDestination,
|
|
361
|
+
});
|
|
362
|
+
node_assert_1.default.notEqual(res.length, 0);
|
|
363
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'txHex'));
|
|
364
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'feeInfo'));
|
|
365
|
+
const rawData = JSON.parse(res.txHex).raw_data;
|
|
366
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(rawData, 'contract'));
|
|
367
|
+
const value = rawData.contract[0].parameter.value;
|
|
368
|
+
node_assert_1.default.equal(value.amount, 100000000);
|
|
369
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.owner_address), resources_1.TestRecoverData.firstReceiveAddress);
|
|
370
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.to_address), resources_1.TestRecoverData.baseAddress);
|
|
371
|
+
});
|
|
372
|
+
(0, node_test_1.it)('should recover token from base address to recovery address', async function () {
|
|
373
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', (...args) => {
|
|
374
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.baseAddress) {
|
|
375
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(100000000, [
|
|
376
|
+
{
|
|
377
|
+
TSdZwNqpHofzP6BsBKGQUWdBeJphLmF6id: '1000000000',
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs: '1100000000',
|
|
381
|
+
},
|
|
382
|
+
]));
|
|
383
|
+
}
|
|
384
|
+
return undefined;
|
|
385
|
+
});
|
|
386
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getTriggerSmartContractTransaction', (...args) => {
|
|
387
|
+
return Promise.resolve(resources_1.SampleRawTokenSendTxn);
|
|
388
|
+
});
|
|
389
|
+
const res = await basecoin.recover({
|
|
390
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
391
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
392
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
393
|
+
tokenContractAddress: 'TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs',
|
|
394
|
+
recoveryDestination: resources_1.TestRecoverData.recoveryDestination,
|
|
395
|
+
});
|
|
396
|
+
node_assert_1.default.notEqual(res.length, 0);
|
|
397
|
+
node_assert_1.default.equal(res.recoveryAmount, 1100000000);
|
|
398
|
+
node_assert_1.default.equal(res.feeInfo.fee, '100000000');
|
|
399
|
+
const expirationDuration = res.tx.raw_data.expiration - res.tx.raw_data.timestamp;
|
|
400
|
+
node_assert_1.default.ok(expirationDuration >= 86400000);
|
|
401
|
+
node_assert_1.default.equal(res.addressInfo, undefined);
|
|
402
|
+
const rawData = JSON.parse(res.txHex).raw_data;
|
|
403
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(rawData, 'contract'));
|
|
404
|
+
const value = rawData.contract[0].parameter.value;
|
|
405
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.owner_address), resources_1.TestRecoverData.baseAddress);
|
|
406
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.contract_address), 'TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs');
|
|
407
|
+
});
|
|
408
|
+
(0, node_test_1.it)('should throw if trx balance at base address is not sufficient to cover token send', async function () {
|
|
409
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', (...args) => {
|
|
410
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.baseAddress) {
|
|
411
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(1000000, [
|
|
412
|
+
{
|
|
413
|
+
TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs: '1100000000',
|
|
414
|
+
},
|
|
415
|
+
]));
|
|
416
|
+
}
|
|
417
|
+
return undefined;
|
|
418
|
+
});
|
|
419
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getTriggerSmartContractTransaction', (...args) => {
|
|
420
|
+
return Promise.resolve(resources_1.SampleRawTokenSendTxn);
|
|
421
|
+
});
|
|
422
|
+
await node_assert_1.default.rejects(basecoin.recover({
|
|
423
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
424
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
425
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
426
|
+
tokenContractAddress: 'TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs',
|
|
427
|
+
recoveryDestination: resources_1.TestRecoverData.recoveryDestination,
|
|
428
|
+
}), {
|
|
429
|
+
message: "Amount of funds to recover 1000000 is less than 100000000 and wouldn't be able to fund a trc20 send",
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
(0, node_test_1.describe)('Build Unsigned Consolidation Recoveries', () => {
|
|
434
|
+
(0, node_test_1.afterEach)(() => {
|
|
435
|
+
node_test_1.mock.reset();
|
|
436
|
+
});
|
|
437
|
+
(0, node_test_1.it)('should throw if startingScanIndex is not ge to 1', async () => {
|
|
438
|
+
await node_assert_1.default.rejects(basecoin.recoverConsolidations({
|
|
439
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
440
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
441
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
442
|
+
startingScanIndex: -1,
|
|
443
|
+
}), {
|
|
444
|
+
message: 'Invalid starting or ending index to scan for addresses. startingScanIndex: -1, endingScanIndex: 19.',
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
(0, node_test_1.it)('should throw if scan factor is too high', async () => {
|
|
448
|
+
await node_assert_1.default.rejects(basecoin.recoverConsolidations({
|
|
449
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
450
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
451
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
452
|
+
startingScanIndex: 1,
|
|
453
|
+
endingScanIndex: 300,
|
|
454
|
+
}), {
|
|
455
|
+
message: 'Invalid starting or ending index to scan for addresses. startingScanIndex: 1, endingScanIndex: 300.',
|
|
456
|
+
});
|
|
457
|
+
});
|
|
458
|
+
(0, node_test_1.it)('should build consolidate recoveries', async () => {
|
|
459
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', (...args) => {
|
|
460
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.firstReceiveAddress) {
|
|
461
|
+
return Promise.resolve((0, resources_1.receiveAddressBalance)(102100000, resources_1.TestRecoverData.firstReceiveAddress));
|
|
462
|
+
}
|
|
463
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.secondReceiveAddress) {
|
|
464
|
+
return Promise.resolve((0, resources_1.receiveAddressBalance)(50000000, resources_1.TestRecoverData.secondReceiveAddress));
|
|
465
|
+
}
|
|
466
|
+
return undefined;
|
|
467
|
+
});
|
|
468
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getBuildTransaction', (...args) => {
|
|
469
|
+
if (args.length > 0 && args[0] === baseAddrHex && args[1] === firstReceiveAddrHex && args[2] === 100000000) {
|
|
470
|
+
return Promise.resolve((0, resources_1.creationTransaction)(firstReceiveAddrHex, baseAddrHex, 100000000));
|
|
471
|
+
}
|
|
472
|
+
if (args.length > 0 && args[0] === baseAddrHex && args[1] === secondReceiveAddrHex && args[2] === 47900000) {
|
|
473
|
+
return Promise.resolve((0, resources_1.creationTransaction)(secondReceiveAddrHex, baseAddrHex, 47900000));
|
|
474
|
+
}
|
|
475
|
+
return undefined;
|
|
476
|
+
});
|
|
477
|
+
const firstReceiveAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.firstReceiveAddress);
|
|
478
|
+
const secondReceiveAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.secondReceiveAddress);
|
|
479
|
+
const baseAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.baseAddress);
|
|
480
|
+
const res = await basecoin.recoverConsolidations({
|
|
481
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
482
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
483
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
484
|
+
startingScanIndex: 1,
|
|
485
|
+
endingScanIndex: 3,
|
|
486
|
+
});
|
|
487
|
+
node_assert_1.default.notEqual(res.length, 0);
|
|
488
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'transactions'));
|
|
489
|
+
node_assert_1.default.equal(res.transactions.length, 2);
|
|
490
|
+
const txn1 = res.transactions[0];
|
|
491
|
+
const rawData1 = JSON.parse(txn1.txHex).raw_data;
|
|
492
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(rawData1, 'contract'));
|
|
493
|
+
const value1 = rawData1.contract[0].parameter.value;
|
|
494
|
+
node_assert_1.default.equal(value1.amount, 100000000);
|
|
495
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value1.owner_address), resources_1.TestRecoverData.firstReceiveAddress);
|
|
496
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value1.to_address), resources_1.TestRecoverData.baseAddress);
|
|
497
|
+
const txn2 = res.transactions[1];
|
|
498
|
+
const rawData2 = JSON.parse(txn2.txHex).raw_data;
|
|
499
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(rawData2, 'contract'));
|
|
500
|
+
const value2 = rawData2.contract[0].parameter.value;
|
|
501
|
+
node_assert_1.default.equal(value2.amount, 47900000);
|
|
502
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value2.owner_address), resources_1.TestRecoverData.secondReceiveAddress);
|
|
503
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value2.to_address), resources_1.TestRecoverData.baseAddress);
|
|
504
|
+
});
|
|
505
|
+
(0, node_test_1.it)('should build consolidate token recoveries', async () => {
|
|
506
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', (...args) => {
|
|
507
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.firstReceiveAddress) {
|
|
508
|
+
return Promise.resolve((0, resources_1.receiveAddressBalance)(202100000, resources_1.TestRecoverData.firstReceiveAddress, [
|
|
509
|
+
{
|
|
510
|
+
TSdZwNqpHofzP6BsBKGQUWdBeJphLmF6id: '1100000000',
|
|
511
|
+
},
|
|
512
|
+
]));
|
|
513
|
+
}
|
|
514
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.secondReceiveAddress) {
|
|
515
|
+
return Promise.resolve((0, resources_1.receiveAddressBalance)(500, resources_1.TestRecoverData.secondReceiveAddress));
|
|
516
|
+
}
|
|
517
|
+
return undefined;
|
|
518
|
+
});
|
|
519
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getBuildTransaction', (...args) => {
|
|
520
|
+
if (args.length > 0 && args[0] === baseAddrHex && args[1] === firstReceiveAddrHex && args[2] === 1100000000) {
|
|
521
|
+
return Promise.resolve((0, resources_1.creationTransaction)(firstReceiveAddrHex, baseAddrHex, 1100000000));
|
|
522
|
+
}
|
|
523
|
+
return undefined;
|
|
524
|
+
});
|
|
525
|
+
const firstReceiveAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.firstReceiveAddress);
|
|
526
|
+
const baseAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.baseAddress);
|
|
527
|
+
const res = await basecoin.recoverConsolidations({
|
|
528
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
529
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
530
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
531
|
+
tokenContractAddress: 'TSdZwNqpHofzP6BsBKGQUWdBeJphLmF6id',
|
|
532
|
+
startingScanIndex: 1,
|
|
533
|
+
endingScanIndex: 3,
|
|
534
|
+
});
|
|
535
|
+
node_assert_1.default.notEqual(res.length, 0);
|
|
536
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'transactions'));
|
|
537
|
+
node_assert_1.default.equal(res.transactions.length, 1);
|
|
538
|
+
const txn = res.transactions[0];
|
|
539
|
+
const rawData = JSON.parse(txn.txHex).raw_data;
|
|
540
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(rawData, 'contract'));
|
|
541
|
+
const value = rawData.contract[0].parameter.value;
|
|
542
|
+
node_assert_1.default.equal(value.data, 'a9059cbb000000000000000000000000c25420255c2c5a2dd54ef69f92ef261e6bd4216a000000000000000000000000000000000000000000000000000000004190ab00');
|
|
543
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.owner_address), resources_1.TestRecoverData.firstReceiveAddress);
|
|
544
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.contract_address), 'TSdZwNqpHofzP6BsBKGQUWdBeJphLmF6id');
|
|
545
|
+
});
|
|
546
|
+
(0, node_test_1.it)('should skip building consolidate transaction if balance is lower than reserved fee', async () => {
|
|
547
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', (...args) => {
|
|
548
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.firstReceiveAddress) {
|
|
549
|
+
return Promise.resolve((0, resources_1.receiveAddressBalance)(102100000, resources_1.TestRecoverData.firstReceiveAddress));
|
|
550
|
+
}
|
|
551
|
+
if (args.length > 0 && args[0] === resources_1.TestRecoverData.secondReceiveAddress) {
|
|
552
|
+
return Promise.resolve((0, resources_1.receiveAddressBalance)(2000000, resources_1.TestRecoverData.secondReceiveAddress));
|
|
553
|
+
}
|
|
554
|
+
return undefined;
|
|
555
|
+
});
|
|
556
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getBuildTransaction', (...args) => {
|
|
557
|
+
if (args.length > 0 && args[0] === baseAddrHex && args[1] === firstReceiveAddrHex && args[2] === 100000000) {
|
|
558
|
+
return Promise.resolve((0, resources_1.creationTransaction)(firstReceiveAddrHex, baseAddrHex, 100000000));
|
|
559
|
+
}
|
|
560
|
+
return undefined;
|
|
561
|
+
});
|
|
562
|
+
const firstReceiveAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.firstReceiveAddress);
|
|
563
|
+
const baseAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TestRecoverData.baseAddress);
|
|
564
|
+
const res = await basecoin.recoverConsolidations({
|
|
565
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
566
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
567
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
568
|
+
startingScanIndex: 1,
|
|
569
|
+
endingScanIndex: 3,
|
|
570
|
+
});
|
|
571
|
+
node_assert_1.default.notEqual(res.length, 0);
|
|
572
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'transactions'));
|
|
573
|
+
node_assert_1.default.equal(res.transactions.length, 1);
|
|
574
|
+
const txn1 = res.transactions[0];
|
|
575
|
+
const rawData1 = JSON.parse(txn1.txHex).raw_data;
|
|
576
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(rawData1, 'contract'));
|
|
577
|
+
const value1 = rawData1.contract[0].parameter.value;
|
|
578
|
+
node_assert_1.default.equal(value1.amount, 100000000);
|
|
579
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value1.owner_address), resources_1.TestRecoverData.firstReceiveAddress);
|
|
580
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value1.to_address), resources_1.TestRecoverData.baseAddress);
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
(0, node_test_1.describe)('TSS Recovery', () => {
|
|
584
|
+
(0, node_test_1.afterEach)(() => {
|
|
585
|
+
node_test_1.mock.reset();
|
|
586
|
+
});
|
|
587
|
+
const walletAddrHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TssTestRecoverData.walletAddress);
|
|
588
|
+
const destinationHex = src_1.Utils.getHexAddressFromBase58Address(resources_1.TssTestRecoverData.recoveryDestination);
|
|
589
|
+
(0, node_test_1.it)('should recover TRX from TSS wallet (unsigned sweep)', async function () {
|
|
590
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', () => {
|
|
591
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(3000000));
|
|
592
|
+
});
|
|
593
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getBuildTransaction', (...args) => {
|
|
594
|
+
if (args[0] === destinationHex && args[1] === walletAddrHex && args[2] === 900000) {
|
|
595
|
+
return Promise.resolve((0, resources_1.creationTransaction)(walletAddrHex, destinationHex, 900000));
|
|
596
|
+
}
|
|
597
|
+
return undefined;
|
|
598
|
+
});
|
|
599
|
+
const res = await basecoin.recover({
|
|
600
|
+
userKey: resources_1.TssTestRecoverData.userKey,
|
|
601
|
+
backupKey: resources_1.TssTestRecoverData.backupKey,
|
|
602
|
+
bitgoKey: resources_1.TssTestRecoverData.bitgoKey,
|
|
603
|
+
recoveryDestination: resources_1.TssTestRecoverData.recoveryDestination,
|
|
604
|
+
isTss: true,
|
|
605
|
+
});
|
|
606
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'txHex'));
|
|
607
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'feeInfo'));
|
|
608
|
+
node_assert_1.default.equal(res.recoveryAmount, 900000);
|
|
609
|
+
const rawData = JSON.parse(res.txHex).raw_data;
|
|
610
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(rawData, 'contract'));
|
|
611
|
+
const value = rawData.contract[0].parameter.value;
|
|
612
|
+
node_assert_1.default.equal(value.amount, 900000);
|
|
613
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.owner_address), resources_1.TssTestRecoverData.walletAddress);
|
|
614
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.to_address), resources_1.TssTestRecoverData.recoveryDestination);
|
|
615
|
+
// unsigned sweep: no signatures
|
|
616
|
+
const sig = JSON.parse(res.txHex).signature;
|
|
617
|
+
node_assert_1.default.ok(!sig || sig.length === 0);
|
|
618
|
+
});
|
|
619
|
+
(0, node_test_1.it)('should recover TRX from TSS wallet (signed recovery)', async function () {
|
|
620
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', () => {
|
|
621
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(3000000));
|
|
622
|
+
});
|
|
623
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getBuildTransaction', (...args) => {
|
|
624
|
+
if (args[0] === destinationHex && args[1] === walletAddrHex && args[2] === 900000) {
|
|
625
|
+
return Promise.resolve((0, resources_1.creationTransaction)(walletAddrHex, destinationHex, 900000));
|
|
626
|
+
}
|
|
627
|
+
return undefined;
|
|
628
|
+
});
|
|
629
|
+
node_test_1.mock.method(bitgo, 'decrypt', () => {
|
|
630
|
+
return Promise.resolve(resources_1.TssTestRecoverData.userPrvKey);
|
|
631
|
+
});
|
|
632
|
+
const res = await basecoin.recover({
|
|
633
|
+
userKey: resources_1.TssTestRecoverData.encryptedUserKey,
|
|
634
|
+
backupKey: resources_1.TssTestRecoverData.encryptedUserKey,
|
|
635
|
+
bitgoKey: resources_1.TssTestRecoverData.bitgoKey,
|
|
636
|
+
recoveryDestination: resources_1.TssTestRecoverData.recoveryDestination,
|
|
637
|
+
walletPassphrase: resources_1.TssTestRecoverData.walletPassphrase,
|
|
638
|
+
isTss: true,
|
|
639
|
+
});
|
|
640
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'txHex'));
|
|
641
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'feeInfo'));
|
|
642
|
+
node_assert_1.default.equal(res.recoveryAmount, 900000);
|
|
643
|
+
const rawData = JSON.parse(res.txHex).raw_data;
|
|
644
|
+
const value = rawData.contract[0].parameter.value;
|
|
645
|
+
node_assert_1.default.equal(value.amount, 900000);
|
|
646
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.owner_address), resources_1.TssTestRecoverData.walletAddress);
|
|
647
|
+
node_assert_1.default.equal(src_1.Utils.getBase58AddressFromHex(value.to_address), resources_1.TssTestRecoverData.recoveryDestination);
|
|
648
|
+
// signed recovery: should have exactly 1 signature
|
|
649
|
+
const sig = JSON.parse(res.txHex).signature;
|
|
650
|
+
node_assert_1.default.equal(sig.length, 1);
|
|
651
|
+
});
|
|
652
|
+
(0, node_test_1.it)('should recover TRC-20 token from TSS wallet (unsigned sweep)', async function () {
|
|
653
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', () => {
|
|
654
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(100000000, [
|
|
655
|
+
{
|
|
656
|
+
TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs: '1100000000',
|
|
657
|
+
},
|
|
658
|
+
]));
|
|
659
|
+
});
|
|
660
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getTriggerSmartContractTransaction', () => {
|
|
661
|
+
return Promise.resolve(resources_1.SampleRawTokenSendTxn);
|
|
662
|
+
});
|
|
663
|
+
const res = await basecoin.recover({
|
|
664
|
+
userKey: resources_1.TssTestRecoverData.userKey,
|
|
665
|
+
backupKey: resources_1.TssTestRecoverData.backupKey,
|
|
666
|
+
bitgoKey: resources_1.TssTestRecoverData.bitgoKey,
|
|
667
|
+
tokenContractAddress: 'TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs',
|
|
668
|
+
recoveryDestination: resources_1.TssTestRecoverData.recoveryDestination,
|
|
669
|
+
isTss: true,
|
|
670
|
+
});
|
|
671
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'txHex'));
|
|
672
|
+
node_assert_1.default.equal(res.recoveryAmount, 1100000000);
|
|
673
|
+
node_assert_1.default.equal(res.feeInfo.fee, '100000000');
|
|
674
|
+
const expirationDuration = res.tx.raw_data.expiration - res.tx.raw_data.timestamp;
|
|
675
|
+
node_assert_1.default.ok(expirationDuration >= 86400000);
|
|
676
|
+
// unsigned sweep: no signatures
|
|
677
|
+
const sig = JSON.parse(res.txHex).signature;
|
|
678
|
+
node_assert_1.default.ok(!sig || sig.length === 0);
|
|
679
|
+
});
|
|
680
|
+
(0, node_test_1.it)('should recover TRC-20 token from TSS wallet (signed recovery)', async function () {
|
|
681
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', () => {
|
|
682
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(100000000, [
|
|
683
|
+
{
|
|
684
|
+
TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs: '1100000000',
|
|
685
|
+
},
|
|
686
|
+
]));
|
|
687
|
+
});
|
|
688
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getTriggerSmartContractTransaction', () => {
|
|
689
|
+
return Promise.resolve(resources_1.SampleRawTokenSendTxn);
|
|
690
|
+
});
|
|
691
|
+
node_test_1.mock.method(bitgo, 'decrypt', () => {
|
|
692
|
+
return Promise.resolve(resources_1.TssTestRecoverData.userPrvKey);
|
|
693
|
+
});
|
|
694
|
+
const res = await basecoin.recover({
|
|
695
|
+
userKey: resources_1.TssTestRecoverData.encryptedUserKey,
|
|
696
|
+
backupKey: resources_1.TssTestRecoverData.encryptedUserKey,
|
|
697
|
+
bitgoKey: resources_1.TssTestRecoverData.bitgoKey,
|
|
698
|
+
tokenContractAddress: 'TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs',
|
|
699
|
+
recoveryDestination: resources_1.TssTestRecoverData.recoveryDestination,
|
|
700
|
+
walletPassphrase: resources_1.TssTestRecoverData.walletPassphrase,
|
|
701
|
+
isTss: true,
|
|
702
|
+
});
|
|
703
|
+
node_assert_1.default.ok(Object.prototype.hasOwnProperty.call(res, 'txHex'));
|
|
704
|
+
node_assert_1.default.equal(res.recoveryAmount, 1100000000);
|
|
705
|
+
node_assert_1.default.equal(res.feeInfo.fee, '100000000');
|
|
706
|
+
// signed recovery: should have exactly 1 signature
|
|
707
|
+
const sig = JSON.parse(res.txHex).signature;
|
|
708
|
+
node_assert_1.default.equal(sig.length, 1);
|
|
709
|
+
});
|
|
710
|
+
(0, node_test_1.it)('should throw if TSS wallet has insufficient balance', async function () {
|
|
711
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', () => {
|
|
712
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(1000000)); // less than SAFE_TRON_TRANSACTION_FEE (2.1e6)
|
|
713
|
+
});
|
|
714
|
+
await node_assert_1.default.rejects(basecoin.recover({
|
|
715
|
+
userKey: resources_1.TssTestRecoverData.userKey,
|
|
716
|
+
backupKey: resources_1.TssTestRecoverData.backupKey,
|
|
717
|
+
bitgoKey: resources_1.TssTestRecoverData.bitgoKey,
|
|
718
|
+
recoveryDestination: resources_1.TssTestRecoverData.recoveryDestination,
|
|
719
|
+
isTss: true,
|
|
720
|
+
}), {
|
|
721
|
+
message: "Amount of funds to recover 1000000 is less than 2100000 and wouldn't be able to fund a send",
|
|
722
|
+
});
|
|
723
|
+
});
|
|
724
|
+
(0, node_test_1.it)('should throw if TRC-20 token not found for TSS wallet', async function () {
|
|
725
|
+
node_test_1.mock.method(src_1.Trx.prototype, 'getAccountBalancesFromNode', () => {
|
|
726
|
+
return Promise.resolve((0, resources_1.baseAddressBalance)(100000000, []));
|
|
727
|
+
});
|
|
728
|
+
await node_assert_1.default.rejects(basecoin.recover({
|
|
729
|
+
userKey: resources_1.TssTestRecoverData.userKey,
|
|
730
|
+
backupKey: resources_1.TssTestRecoverData.backupKey,
|
|
731
|
+
bitgoKey: resources_1.TssTestRecoverData.bitgoKey,
|
|
732
|
+
tokenContractAddress: 'TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs',
|
|
733
|
+
recoveryDestination: resources_1.TssTestRecoverData.recoveryDestination,
|
|
734
|
+
isTss: true,
|
|
735
|
+
}), sdk_core_1.ErrorNoInputToRecover);
|
|
736
|
+
});
|
|
737
|
+
});
|
|
738
|
+
(0, node_test_1.describe)('Recover Provider Failure', () => {
|
|
739
|
+
(0, node_test_1.afterEach)(() => {
|
|
740
|
+
node_test_1.mock.reset();
|
|
741
|
+
nock_1.default.cleanAll();
|
|
742
|
+
});
|
|
743
|
+
(0, node_test_1.it)('should throw RecoveryProviderError when the Tron node is unreachable', async () => {
|
|
744
|
+
(0, nock_1.default)('https://api.shasta.trongrid.io')
|
|
745
|
+
.get(/\/v1\/accounts\/.*/)
|
|
746
|
+
.reply(500, { error: 'node unavailable' });
|
|
747
|
+
await node_assert_1.default.rejects(basecoin.recover({
|
|
748
|
+
userKey: resources_1.TestRecoverData.userKey,
|
|
749
|
+
backupKey: resources_1.TestRecoverData.backupKey,
|
|
750
|
+
bitgoKey: resources_1.TestRecoverData.bitgoKey,
|
|
751
|
+
recoveryDestination: resources_1.TestRecoverData.recoveryDestination,
|
|
752
|
+
}), sdk_core_1.RecoveryProviderError);
|
|
753
|
+
});
|
|
754
|
+
});
|
|
755
|
+
(0, node_test_1.describe)('isWalletAddress', () => {
|
|
756
|
+
(0, node_test_1.it)('should verify root address (index 0)', async function () {
|
|
757
|
+
const result = await basecoin.isWalletAddress({
|
|
758
|
+
address: testWalletData.rootAddress,
|
|
759
|
+
keychains: testWalletData.keychains,
|
|
760
|
+
index: 0,
|
|
761
|
+
});
|
|
762
|
+
node_assert_1.default.equal(result, true);
|
|
763
|
+
});
|
|
764
|
+
(0, node_test_1.it)('should verify receive address (index > 0)', async function () {
|
|
765
|
+
const result = await basecoin.isWalletAddress({
|
|
766
|
+
address: testWalletData.receiveAddress,
|
|
767
|
+
keychains: testWalletData.keychains,
|
|
768
|
+
index: testWalletData.receiveAddressIndex,
|
|
769
|
+
chain: 0,
|
|
770
|
+
});
|
|
771
|
+
node_assert_1.default.equal(result, true);
|
|
772
|
+
});
|
|
773
|
+
(0, node_test_1.it)('should verify address with index in coinSpecific', async function () {
|
|
774
|
+
const result = await basecoin.isWalletAddress({
|
|
775
|
+
address: testWalletData.rootAddress,
|
|
776
|
+
keychains: testWalletData.keychains,
|
|
777
|
+
coinSpecific: { index: 0 },
|
|
778
|
+
});
|
|
779
|
+
node_assert_1.default.equal(result, true);
|
|
780
|
+
});
|
|
781
|
+
(0, node_test_1.it)('should verify address with string index', async function () {
|
|
782
|
+
const result = await basecoin.isWalletAddress({
|
|
783
|
+
address: testWalletData.rootAddress,
|
|
784
|
+
keychains: testWalletData.keychains,
|
|
785
|
+
index: '0',
|
|
786
|
+
});
|
|
787
|
+
node_assert_1.default.equal(result, true);
|
|
788
|
+
});
|
|
789
|
+
(0, node_test_1.it)('should return false for wrong address at index 0', async function () {
|
|
790
|
+
const result = await basecoin.isWalletAddress({
|
|
791
|
+
address: testWalletData.receiveAddress, // wrong address for index 0
|
|
792
|
+
keychains: testWalletData.keychains,
|
|
793
|
+
index: 0,
|
|
794
|
+
});
|
|
795
|
+
node_assert_1.default.equal(result, false);
|
|
796
|
+
});
|
|
797
|
+
(0, node_test_1.it)('should return false for wrong address at receive index', async function () {
|
|
798
|
+
const result = await basecoin.isWalletAddress({
|
|
799
|
+
address: testWalletData.rootAddress, // wrong address for index 1
|
|
800
|
+
keychains: testWalletData.keychains,
|
|
801
|
+
index: testWalletData.receiveAddressIndex,
|
|
802
|
+
chain: 0,
|
|
803
|
+
});
|
|
804
|
+
node_assert_1.default.equal(result, false);
|
|
805
|
+
});
|
|
806
|
+
(0, node_test_1.it)('should throw for invalid address', async function () {
|
|
807
|
+
await node_assert_1.default.rejects(basecoin.isWalletAddress({
|
|
808
|
+
address: 'invalid-address',
|
|
809
|
+
keychains: testWalletData.keychains,
|
|
810
|
+
index: 0,
|
|
811
|
+
}), {
|
|
812
|
+
message: 'Invalid address: invalid-address',
|
|
813
|
+
});
|
|
814
|
+
});
|
|
815
|
+
(0, node_test_1.it)('should throw for missing index', async function () {
|
|
816
|
+
await node_assert_1.default.rejects(basecoin.isWalletAddress({
|
|
817
|
+
address: testWalletData.rootAddress,
|
|
818
|
+
keychains: testWalletData.keychains,
|
|
819
|
+
}), {
|
|
820
|
+
message: 'Invalid or missing index for address verification',
|
|
821
|
+
});
|
|
822
|
+
});
|
|
823
|
+
(0, node_test_1.it)('should throw for missing bitgo key on root address verification', async function () {
|
|
824
|
+
await node_assert_1.default.rejects(basecoin.isWalletAddress({
|
|
825
|
+
address: testWalletData.rootAddress,
|
|
826
|
+
keychains: testWalletData.keychains.slice(0, 2), // only user and backup keys
|
|
827
|
+
index: 0,
|
|
828
|
+
}), {
|
|
829
|
+
message: 'BitGo public key required for root address verification',
|
|
830
|
+
});
|
|
831
|
+
});
|
|
832
|
+
(0, node_test_1.it)('should throw for missing user key on receive address verification', async function () {
|
|
833
|
+
await node_assert_1.default.rejects(basecoin.isWalletAddress({
|
|
834
|
+
address: testWalletData.receiveAddress,
|
|
835
|
+
keychains: [], // no keys
|
|
836
|
+
index: testWalletData.receiveAddressIndex,
|
|
837
|
+
}), {
|
|
838
|
+
message: 'User public key required for receive address verification',
|
|
839
|
+
});
|
|
840
|
+
});
|
|
841
|
+
});
|
|
842
|
+
});
|
|
843
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJ4LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L3RyeC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDhEQUFpQztBQUNqQyx5Q0FBa0U7QUFDbEUsaURBQStDO0FBQy9DLG1EQUFvRjtBQUNwRixtREFBK0Q7QUFDL0QsMENBQTRCO0FBQzVCLGdEQUF3QjtBQUN4QixtQ0FBNkM7QUFDN0MsMENBQW9EO0FBQ3BELDRDQU9zQjtBQUV0QixJQUFBLG9CQUFRLEVBQUMsT0FBTyxFQUFFO0lBQ2hCLE1BQU0sS0FBSyxHQUFpQixvQkFBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDMUUsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7SUFDM0IsS0FBSyxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsU0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQzlDLEtBQUssQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLFVBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUVoRCxJQUFJLFFBQVEsQ0FBQztJQUViLHlEQUF5RDtJQUN6RCxNQUFNLGNBQWMsR0FBRztRQUNyQixXQUFXLEVBQUUsb0NBQW9DO1FBQ2pELGNBQWMsRUFBRSxvQ0FBb0M7UUFDcEQsbUJBQW1CLEVBQUUsQ0FBQztRQUN0QixTQUFTLEVBQUU7WUFDVDtnQkFDRSxFQUFFLEVBQUUsa0NBQWtDO2dCQUN0QyxHQUFHLEVBQUUsaUhBQWlIO2FBQ3ZIO1lBQ0Q7Z0JBQ0UsRUFBRSxFQUFFLGtDQUFrQztnQkFDdEMsR0FBRyxFQUFFLGlIQUFpSDthQUN2SDtZQUNEO2dCQUNFLEVBQUUsRUFBRSxrQ0FBa0M7Z0JBQ3RDLEdBQUcsRUFBRSxpSEFBaUg7YUFDdkg7U0FDRjtLQUNGLENBQUM7SUFFRixJQUFBLGtCQUFNLEVBQUM7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dkIsT0FBTyxFQUFFLGNBQWMsQ0FBQyxjQUFjO2dCQUN0QyxTQUFTLEVBQUUsRUFBRSxFQUFFLFVBQVU7Z0JBQ3pCLEtBQUssRUFBRSxjQUFjLENBQUMsbUJBQW1CO2FBQzFDLENBQUMsRUFDRjtnQkFDRSxPQUFPLEVBQUUsMkRBQTJEO2FBQ3JFLENBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSAnbm9kZTphc3NlcnQnO1xuaW1wb3J0IHsgYWZ0ZXJFYWNoLCBiZWZvcmUsIGRlc2NyaWJlLCBpdCwgbW9jayB9IGZyb20gJ25vZGU6dGVzdCc7XG5pbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1hcGknO1xuaW1wb3J0IHsgRXJyb3JOb0lucHV0VG9SZWNvdmVyLCBSZWNvdmVyeVByb3ZpZGVyRXJyb3IgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBUZXN0Qml0R29BUEksIFRlc3RCaXRHbyB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay10ZXN0JztcbmltcG9ydCAqIGFzIF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBub2NrIGZyb20gJ25vY2snO1xuaW1wb3J0IHsgVHJ4LCBUdHJ4LCBVdGlscyB9IGZyb20gJy4uLy4uL3NyYyc7XG5pbXBvcnQgeyBzaWduVHhPcHRpb25zLCBtb2NrVHggfSBmcm9tICcuLi9maXh0dXJlcyc7XG5pbXBvcnQge1xuICBiYXNlQWRkcmVzc0JhbGFuY2UsXG4gIFNhbXBsZVJhd1Rva2VuU2VuZFR4bixcbiAgcmVjZWl2ZUFkZHJlc3NCYWxhbmNlLFxuICBUZXN0UmVjb3ZlckRhdGEsXG4gIFRzc1Rlc3RSZWNvdmVyRGF0YSxcbiAgY3JlYXRpb25UcmFuc2FjdGlvbixcbn0gZnJvbSAnLi4vcmVzb3VyY2VzJztcblxuZGVzY3JpYmUoJ1RST046JywgZnVuY3Rpb24gKCkge1xuICBjb25zdCBiaXRnbzogVGVzdEJpdEdvQVBJID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0cngnLCBUcnguY3JlYXRlSW5zdGFuY2UpO1xuICBiaXRnby5zYWZlUmVnaXN0ZXIoJ3R0cngnLCBUdHJ4LmNyZWF0ZUluc3RhbmNlKTtcblxuICBsZXQgYmFzZWNvaW47XG5cbiAgLy8gVGVzdCBkYXRhIGZyb20gd2FsbGV0IDY5M2IwMTFhM2VjMjY5ODZmNTY5YjAyMTQwYzc2MjdlXG4gIGNvbnN0IHRlc3RXYWxsZXREYXRhID0ge1xuICAgIHJvb3RBZGRyZXNzOiAnVEFmMzZiMzZlcW9NQ3pKSm0zandTc1A4MVV2a014clBiaScsXG4gICAgcmVjZWl2ZUFkZHJlc3M6ICdURmFENkRlS0ZNY0J1R3VERDdMYmJxeFRuS3VuaFhmZHlhJyxcbiAgICByZWNlaXZlQWRkcmVzc0luZGV4OiAyLFxuICAgIGtleWNoYWluczogW1xuICAgICAge1xuICAgICAgICBpZDogJzY5M2IwMTEwMjcxZmMzZjU3NDk3NTQwOTc3OTNiYjhkJyxcbiAgICAgICAgcHViOiAneHB1YjY2MU15TXdBcVJiY0ZzVkFkWnlOMm04cDIxV0hYZzhOUk5rcUtBcHlTNWd3bUZzUGRSVHJtSFlDbnpSOXZZZThEUTR1V0dDQmNBQXNXRTNyOTdIc0ZTM0syZmFaMmVqWE5oSHhkRW9BRVdDJyxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGlkOiAnNjkzYjAxMTA2NWI5YzQ2NzQ4MjVjZTFmODQ5YjdiZWYnLFxuICAgICAgICBwdWI6ICd4cHViNjYxTXlNd0FxUmJjRXJLcFpyOXp0VEZKazZmelhXYXRNRmdSbnBYZnNqeWJXQmZFOTg0N0VWR3JISEJzR1A4ZmNuekptSnVldkFiUFVFcGpIVGpFRVdmWVVXTk1FRGFodnNzUWVpbjg0OG8nLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgaWQ6ICc2OTNiMDExMTdjNDE4NDZhYmIwNDgxODgxNWI4OWI2YycsXG4gICAgICAgIHB1YjogJ3hwdWI2NjFNeU13QXFSYmNGcVpkN1hVOURGVzRmMjlWSnpRdDdVQ0E1MXlwYVdhNXltaFEycFJaRFRnVml3M3ZaNTZQcVo4ZGoxY3JhY04zZkFXaGFpRzFRS2o5bXZ5dDlDYmE0bk0ydFBpYk5LdycsXG4gICAgICB9LFxuICAgIF0sXG4gIH07XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiYXNlY29pbiA9IGJpdGdvLmNvaW4oJ3R0cngnKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBpbnN0YW50aWF0ZSB0aGUgY29pbicsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBiYXNlY29pbiA9IGJpdGdvLmNvaW4oJ3RyeCcpO1xuICAgIGFzc2VydC5vayhiYXNlY29pbiBpbnN0YW5jZW9mIFRyeCk7XG4gIH0pO1xuXG4gIGl0KCdleHBsYWluIGEgdHhIZXgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHhIZXggPSBKU09OLnN0cmluZ2lmeShtb2NrVHgpO1xuICAgIGNvbnN0IGV4cGxhaW5QYXJhbXMgPSB7XG4gICAgICB0eEhleCxcbiAgICAgIGZlZUluZm86IHsgZmVlOiAxIH0sXG4gICAgICB0eElEOiBtb2NrVHgudHhJRCxcbiAgICB9O1xuICAgIGNvbnN0IGV4cGxhbmF0aW9uID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKGV4cGxhaW5QYXJhbXMpO1xuICAgIGNvbnN0IHRvQWRkcmVzcyA9IFV0aWxzLmdldEJhc2U1OEFkZHJlc3NGcm9tSGV4KG1vY2tUeC5yYXdfZGF0YS5jb250cmFjdFswXS5wYXJhbWV0ZXIudmFsdWUudG9fYWRkcmVzcyk7XG4gICAgYXNzZXJ0LmVxdWFsKGV4cGxhbmF0aW9uLmlkLCBtb2NrVHgudHhJRCk7XG4gICAgYXNzZXJ0LmVxdWFsKGV4cGxhbmF0aW9uLm91dHB1dHMubGVuZ3RoLCAxKTtcbiAgICBhc3NlcnQuZXF1YWwoZXhwbGFuYXRpb24ub3V0cHV0c1swXS5hbW91bnQsICcxMCcpO1xuICAgIGFzc2VydC5lcXVhbChleHBsYW5hdGlvbi5vdXRwdXRzWzBdLmFkZHJlc3MsIHRvQWRkcmVzcyk7XG4gICAgYXNzZXJ0LmVxdWFsKGV4cGxhbmF0aW9uLm91dHB1dEFtb3VudCwgJzEwJyk7XG4gICAgYXNzZXJ0LmVxdWFsKGV4cGxhbmF0aW9uLmNoYW5nZUFtb3VudCwgJzAnKTtcbiAgICBhc3NlcnQuZXF1YWwoZXhwbGFuYXRpb24uY2hhbmdlT3V0cHV0cy5sZW5ndGgsIDApO1xuICAgIGFzc2VydC5lcXVhbChleHBsYW5hdGlvbi5mZWUuZmVlLCAxKTtcbiAgICBhc3NlcnQuZXF1YWwoZXhwbGFuYXRpb24uZXhwaXJhdGlvbiwgbW9ja1R4LnJhd19kYXRhLmV4cGlyYXRpb24pO1xuICAgIGFzc2VydC5lcXVhbChleHBsYW5hdGlvbi50aW1lc3RhbXAsIG1vY2tUeC5yYXdfZGF0YS50aW1lc3RhbXApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGNoZWNrIHZhbGlkIGFkZHJlc3NlcycsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBiYWRBZGRyZXNzZXMgPSBbXG4gICAgICAnJyxcbiAgICAgIG51bGwsXG4gICAgICAneHh4eCcsXG4gICAgICAnWVowOWZkLScsXG4gICAgICAnNDEyQzJCQTRBOUZGNkM1MzIwN0RDNUI2ODZCRkVDRjc1RUE3QjgwNTc3MicsIC8vIDQzIGhleCBjaGFycyDigJQgdG9vIGxvbmdcbiAgICAgICc0MTJDMkJBNEE5RkY2QzUzMjA3REM1QjY4NkJGRUNGNzVFQTdCODAnLCAvLyB0b28gc2hvcnRcbiAgICAgICdUQkNod0tZTmFUbzRhNE42OE1lMXFFaWlLc1JEc3BYcUxMWicsIC8vIGludmFsaWQgYmFzZTU4IGNoZWNrc3VtXG4gICAgICAnMHgzNDFxZzM5MjJiMScsIC8vIG5vbi1oZXhcbiAgICAgICc5NmJlMTEzOTkyYmRjM2JlMjRjMTFmNjAxNzA4NWI2MDVkMjUzNjQ5JywgLy8gYmFyZSAyMC1ieXRlIOKAlCBub3QgYW4gb24tY2hhaW4gYWRkcmVzcyBmb3JtXG4gICAgXTtcbiAgICAvLyBiYXNlNTggYW5kIGhleCAoMHggLyA0MSkgYXJlIGFsdGVybmF0aXZlIGVuY29kaW5ncyBvZiB0aGUgc2FtZSBhZGRyZXNzIChDT0lOUy0xNTc1KVxuICAgIGNvbnN0IGdvb2RBZGRyZXNzZXMgPSBbXG4gICAgICAnVEJDaHdLWU5hVG80YTRONjhNZTFxRWlpS3NSRHNwWHFMcCcsXG4gICAgICAnVFBjZjVqdFlVaENOMVgxNHRONTc3ekY0TmVwYkRaYnhUNycsXG4gICAgICAnMHg5NmJlMTEzOTkyYmRjM2JlMjRjMTFmNjAxNzA4NWI2MDVkMjUzNjQ5JyxcbiAgICAgICc0MUUwQzBGNTgxRDdEMDJENDA4MjZDMUM2Q0JFRTcxRjYyNUQ2MzQ0RDAnLFxuICAgICAgJzQxMkMyQkE0QTlGRjZDNTMyMDdEQzVCNjg2QkZFQ0Y3NUVBN0I4MDU3NycsXG4gICAgICAnNDE4ODQwRTZDNTVCOUFEQTMyNkQyMTFEODE4QzM0QTk5NEFFQ0VEODA4JyxcbiAgICAgICc0MTJBMkI5Rjc2NDFEMDc1MEMxRTgyMkQwRTQ5RUY3NjVDODEwNjUyNEInLFxuICAgICAgJzQxQTYxNEY4MDNCNkZENzgwOTg2QTQyQzc4RUM5QzdGNzdFNkRFRDEzQycsXG4gICAgXTtcblxuICAgIGJhZEFkZHJlc3Nlcy5tYXAoKGFkZHIpID0+IHtcbiAgICAgIGFzc2VydC5lcXVhbChiYXNlY29pbi5pc1ZhbGlkQWRkcmVzcyhhZGRyIGFzIHN0cmluZyksIGZhbHNlKTtcbiAgICB9KTtcbiAgICBnb29kQWRkcmVzc2VzLm1hcCgoYWRkcikgPT4ge1xuICAgICAgYXNzZXJ0LmVxdWFsKGJhc2Vjb2luLmlzVmFsaWRBZGRyZXNzKGFkZHIpLCB0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBjYW5vbmljYWxpemUgaGV4IGFkZHJlc3NlcyB0byBiYXNlNTggKENPSU5TLTE1NzUpJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJhc2U1OCA9ICdUR2FpNXVIZ0Jjb0xFUnJ6RFhNZXBxWkI4RXQ3RDhuVjhLJztcbiAgICBjb25zdCBoZXg0MSA9ICc0MTQ4ODc5NzRmNDJhNzg5ZWY2ZDRkZmM3YmEyOGIxNTgzMjE5NDM0YjMnO1xuICAgIGNvbnN0IGhleDB4ID0gJzB4NDg4Nzk3NGY0MmE3ODllZjZkNGRmYzdiYTI4YjE1ODMyMTk0MzRiMyc7XG5cbiAgICBhc3NlcnQuZXF1YWwoYmFzZWNvaW4uY2Fub25pY2FsQWRkcmVzcyhiYXNlNTgpLCBiYXNlNTgpO1xuICAgIGFzc2VydC5lcXVhbChiYXNlY29pbi5jYW5vbmljYWxBZGRyZXNzKGhleDQxKSwgYmFzZTU4KTtcbiAgICBhc3NlcnQuZXF1YWwoYmFzZWNvaW4uY2Fub25pY2FsQWRkcmVzcyhoZXgweCksIGJhc2U1OCk7XG4gICAgYXNzZXJ0LmVxdWFsKGJhc2Vjb2luLmNhbm9uaWNhbEFkZHJlc3MoJ25vdC1hbi1hZGRyZXNzJyksICdub3QtYW4tYWRkcmVzcycpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlamVjdCBoZXggZm9ybXMgaW4gc3RyaWN0IEJhc2U1OCBtb2RlJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJhc2U1OCA9ICdUR2FpNXVIZ0Jjb0xFUnJ6RFhNZXBxWkI4RXQ3RDhuVjhLJztcbiAgICBjb25zdCBoZXg0MSA9ICc0MTQ4ODc5NzRmNDJhNzg5ZWY2ZDRkZmM3YmEyOGIxNTgzMjE5NDM0YjMnO1xuICAgIGNvbnN0IGhleDB4ID0gJzB4NDg4Nzk3NGY0MmE3ODllZjZkNGRmYzdiYTI4YjE1ODMyMTk0MzRiMyc7XG5cbiAgICAvLyBkZWZhdWx0IGJlaGF2aW9yIHVuY2hhbmdlZDogYWxsIHRocmVlIGZvcm1zIGFjY2VwdGVkXG4gICAgYXNzZXJ0LmVxdWFsKGJhc2Vjb2luLmlzVmFsaWRBZGRyZXNzKGJhc2U1OCksIHRydWUpO1xuICAgIGFzc2VydC5lcXVhbChiYXNlY29pbi5pc1ZhbGlkQWRkcmVzcyhoZXg0MSksIHRydWUpO1xuICAgIGFzc2VydC5lcXVhbChiYXNlY29pbi5pc1ZhbGlkQWRkcmVzcyhoZXgweCksIHRydWUpO1xuXG4gICAgLy8gc3RyaWN0QmFzZTU4OiBvbmx5IGNhbm9uaWNhbCBCYXNlNTggYWNjZXB0ZWRcbiAgICBhc3NlcnQuZXF1YWwoYmFzZWNvaW4uaXNWYWxpZEFkZHJlc3MoYmFzZTU4LCB7IHN0cmljdEJhc2U1ODogdHJ1ZSB9KSwgdHJ1ZSk7XG4gICAgYXNzZXJ0LmVxdWFsKGJhc2Vjb2luLmlzVmFsaWRBZGRyZXNzKGhleDQxLCB7IHN0cmljdEJhc2U1ODogdHJ1ZSB9KSwgZmFsc2UpO1xuICAgIGFzc2VydC5lcXVhbChiYXNlY29pbi5pc1ZhbGlkQWRkcmVzcyhoZXgweCwgeyBzdHJpY3RCYXNlNTg6IHRydWUgfSksIGZhbHNlKTtcbiAgICBhc3NlcnQuZXF1YWwoYmFzZWNvaW4uaXNWYWxpZEFkZHJlc3MoJycsIHsgc3RyaWN0QmFzZTU4OiB0cnVlIH0pLCBmYWxzZSk7XG4gICAgYXNzZXJ0LmVxdWFsKGJhc2Vjb2luLmlzVmFsaWRBZGRyZXNzKCdUQkNod0tZTmFUbzRhNE42OE1lMXFFaWlLc1JEc3BYcUxMWicsIHsgc3RyaWN0QmFzZTU4OiB0cnVlIH0pLCBmYWxzZSk7XG5cbiAgICAvLyBleHBsaWNpdCBmYWxzZSBrZWVwcyBsZW5pZW50IGJlaGF2aW9yXG4gICAgYXNzZXJ0LmVxdWFsKGJhc2Vjb2luLmlzVmFsaWRBZGRyZXNzKGhleDB4LCB7IHN0cmljdEJhc2U1ODogZmFsc2UgfSksIHRydWUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IGlmIHRoZSBwYXJhbXMgb2JqZWN0IGlzIG1pc3NpbmcgcGFyYW1ldGVycycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBleHBsYWluUGFyYW1zID0ge1xuICAgICAgZmVlSW5mbzogeyBmZWU6IDEgfSxcbiAgICAgIHR4SUQ6IG1vY2tUeC50eElELFxuICAgICAgdHhIZXg6IG51bGwsXG4gICAgfTtcbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oZXhwbGFpblBhcmFtcyksIHtcbiAgICAgIG1lc3NhZ2U6ICdtaXNzaW5nIGV4cGxhaW4gdHggcGFyYW1ldGVycycsXG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KCdleHBsYWluIGFuIGhhbGYtc2lnbmVkL2Z1bGx5IHNpZ25lZCB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eEhleCA9IEpTT04uc3RyaW5naWZ5KG1vY2tUeCk7XG4gICAgY29uc3QgZXhwbGFpblBhcmFtcyA9IHtcbiAgICAgIGhhbGZTaWduZWQ6IHsgdHhIZXggfSxcbiAgICAgIGZlZUluZm86IHsgZmVlOiAxIH0sXG4gICAgICB0eElEOiBtb2NrVHgudHhJRCxcbiAgICB9O1xuICAgIGNvbnN0IGV4cGxhbmF0aW9uID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKGV4cGxhaW5QYXJhbXMpO1xuICAgIGNvbnN0IHRvQWRkcmVzcyA9IFV0aWxzLmdldEJhc2U1OEFkZHJlc3NGcm9tSGV4KG1vY2tUeC5yYXdfZGF0YS5jb250cmFjdFswXS5wYXJhbWV0ZXIudmFsdWUudG9fYWRkcmVzcyk7XG4gICAgYXNzZXJ0LmVxdWFsKGV4cGxhbmF0aW9uLmlkLCBtb2NrVHgudHhJRCk7XG4gICAgYXNzZXJ0LmVxdWFsKGV4cGxhbmF0aW9uLm91dHB1dHMubGVuZ3RoLCAxKTtcbiAgICBhc3NlcnQuZXF1YWwoZXhwbGFuYXRpb24ub3V0cHV0c1swXS5hbW91bnQsICcxMCcpO1xuICAgIGFzc2VydC5lcXVhbChleHBsYW5hdGlvbi5vdXRwdXRzWzBdLmFkZHJlc3MsIHRvQWRkcmVzcyk7XG4gICAgYXNzZXJ0LmVxdWFsKGV4cGxhbmF0aW9uLm91dHB1dEFtb3VudCwgJzEwJyk7XG4gICAgYXNzZXJ0LmVxdWFsKGV4cGxhbmF0aW9uLmNoYW5nZUFtb3VudCwgJzAnKTtcbiAgICBhc3NlcnQuZXF1YWwoZXhwbGFuYXRpb24uY2hhbmdlT3V0cHV0cy5sZW5ndGgsIDApO1xuICAgIGFzc2VydC5lcXVhbChleHBsYW5hdGlvbi5mZWUuZmVlLCAxKTtcbiAgICBhc3NlcnQuZXF1YWwoZXhwbGFuYXRpb24uZXhwaXJhdGlvbiwgbW9ja1R4LnJhd19kYXRhLmV4cGlyYXRpb24pO1xuICAgIGFzc2VydC5lcXVhbChleHBsYW5hdGlvbi50aW1lc3RhbXAsIG1vY2tUeC5yYXdfZGF0YS50aW1lc3RhbXApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHNpZ24gYSBoYWxmIHNpZ25lZCB0eCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbihzaWduVHhPcHRpb25zKTtcbiAgICBjb25zdCB1bnNpZ25lZFR4SnNvbiA9IEpTT04ucGFyc2Uoc2lnblR4T3B0aW9ucy50eFByZWJ1aWxkLnR4SGV4KTtcbiAgICBjb25zdCBzaWduZWRUeEpzb24gPSBKU09OLnBhcnNlKHR4LmhhbGZTaWduZWQudHhIZXgpO1xuXG4gICAgYXNzZXJ0LmVxdWFsKHNpZ25lZFR4SnNvbi50eElELCB1bnNpZ25lZFR4SnNvbi50eElEKTtcbiAgICBhc3NlcnQuZXF1YWwoc2lnbmVkVHhKc29uLnJhd19kYXRhX2hleCwgdW5zaWduZWRUeEpzb24ucmF3X2RhdGFfaGV4KTtcbiAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKEpTT04uc3RyaW5naWZ5KHNpZ25lZFR4SnNvbi5yYXdfZGF0YSksIEpTT04uc3RyaW5naWZ5KHVuc2lnbmVkVHhKc29uLnJhd19kYXRhKSk7XG4gICAgYXNzZXJ0LmVxdWFsKHNpZ25lZFR4SnNvbi5zaWduYXR1cmUubGVuZ3RoLCAxKTtcbiAgICBhc3NlcnQuZXF1YWwoXG4gICAgICBzaWduZWRUeEpzb24uc2lnbmF0dXJlWzBdLFxuICAgICAgJzBhOTk0NDMxNjkyNGVjN2ZiYTQ4OTVmMWVhMWU3Y2M5NWY5ZTJiODI4YWUyNjhhNDhhOGRiZWRkZWY0MGM2ZjVlMTI3MTcwYTk1YWVkOWYzZjU0MjViMTMwNThkMGNiNmVmMWY1YzIyMTMxOTBlNDgyZTg3MDQzNjkxZjIyZTY4MDAnXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBzaWduIHdpdGggYW4gWHBydiBhIGhhbGYgc2lnbmVkIHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHAgPSB7XG4gICAgICBwcnY6ICd4cHJ2OXMyMVpyUUgxNDNLMnNnMkN1a2s1WHFMUWRyWW5NQ0RhaDN5MUZGVnk2SHo5YlFmcU1TZm1VaUhQVkhLaGNVeWZ0M04xZW1FNUZ1ZEpWeGdGbTVOMTJNQWc1bzdEVFBzREFUVGt3TmdyNzMnLFxuICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICB0eEhleDogc2lnblR4T3B0aW9ucy50eFByZWJ1aWxkLnR4SGV4LFxuICAgICAgfSxcbiAgICB9O1xuICAgIGNvbnN0IHR4ID0gYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKHApO1xuICAgIGNvbnN0IHVuc2lnbmVkVHhKc29uID0gSlNPTi5wYXJzZShzaWduVHhPcHRpb25zLnR4UHJlYnVpbGQudHhIZXgpO1xuICAgIGNvbnN0IHNpZ25lZFR4SnNvbiA9IEpTT04ucGFyc2UodHguaGFsZlNpZ25lZC50eEhleCk7XG5cbiAgICBhc3NlcnQuZXF1YWwoc2lnbmVkVHhKc29uLnR4SUQsIHVuc2lnbmVkVHhKc29uLnR4SUQpO1xuICAgIGFzc2VydC5lcXVhbChzaWduZWRUeEpzb24ucmF3X2RhdGFfaGV4LCB1bnNpZ25lZFR4SnNvbi5yYXdfZGF0YV9oZXgpO1xuICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoSlNPTi5zdHJpbmdpZnkoc2lnbmVkVHhKc29uLnJhd19kYXRhKSwgSlNPTi5zdHJpbmdpZnkodW5zaWduZWRUeEpzb24ucmF3X2RhdGEpKTtcbiAgICBhc3NlcnQuZXF1YWwoc2lnbmVkVHhKc29uLnNpZ25hdHVyZS5sZW5ndGgsIDEpO1xuICAgIGFzc2VydC5lcXVhbChcbiAgICAgIHNpZ25lZFR4SnNvbi5zaWduYXR1cmVbMF0sXG4gICAgICAnNjVlNTZmNTNhNDU4YzZmODJkMWVmMzliMmNmNWJlNjg1YTkwNmFkMjJiYjAyNjk5ZjkwN2ZjYjcyZWYyNmYxZTkxY2ZjMmI2YTQzYmY1NDMyZmFhMGI2M2JkYzVhZWJmMWRjMmY0OWE2NzVkMjhkMjNmZDdlMDM4YjMzNThiMDYwMCdcbiAgICApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGFkZCBmZWVMaW1pdCB0byByZWNpcGllbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgZmVlTGltaXQgPSAxMDA7XG4gICAgY29uc3QgYnVpbGRQYXJhbXMgPSB7XG4gICAgICByZWNpcGllbnRzOiBbeyBkYXRhOiAndGVzdCcgfV0sXG4gICAgICBmZWVMaW1pdCxcbiAgICB9O1xuICAgIGJhc2Vjb2luLmdldEV4dHJhUHJlYnVpbGRQYXJhbXMoYnVpbGRQYXJhbXMpO1xuICAgIGFzc2VydC5lcXVhbCgoYnVpbGRQYXJhbXMgYXMgYW55KS5yZWNpcGllbnRzWzBdLmZlZUxpbWl0LCBmZWVMaW1pdCk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGRgdCBhZGQgYW55IG5ldyBmaWVsZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBidWlsZFBhcmFtcyA9IHtcbiAgICAgIHJlY2lwaWVudHM6IFt7IGRhdGE6ICd0ZXN0JyB9XSxcbiAgICB9O1xuICAgIGNvbnN0IHVubW9kaWZpZWRCdWlsZFBhcmFtcyA9IF8uY2xvbmVEZWVwKGJ1aWxkUGFyYW1zKTtcbiAgICBhd2FpdCBiYXNlY29pbi5nZXRFeHRyYVByZWJ1aWxkUGFyYW1zKGJ1aWxkUGFyYW1zKTtcbiAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKGJ1aWxkUGFyYW1zLCB1bm1vZGlmaWVkQnVpbGRQYXJhbXMpO1xuICB9KTtcblxuICBkZXNjcmliZSgnS2V5cGFpcnM6JywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUgYSBrZXlwYWlyIGZyb20gcmFuZG9tIHNlZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBrZXlQYWlyID0gYmFzZWNvaW4uZ2VuZXJhdGVLZXlQYWlyKCk7XG4gICAgICBhc3NlcnQub2soT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGtleVBhaXIsICdwdWInKSk7XG4gICAgICBhc3NlcnQub2soT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGtleVBhaXIsICdwcnYnKSk7XG4gICAgICBhc3NlcnQuZXF1YWwoYmFzZWNvaW4uaXNWYWxpZFB1YihrZXlQYWlyLnB1YiksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBhIGtleXBhaXIgZnJvbSBhIHNlZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzZWVkVGV4dCA9XG4gICAgICAgICc4MDM1MGI0MjA4ZDM4MWZiZmUyMjc2YTMyNjYwMzA0OWZlNTAwNzMxYzQ2ZDNjOTkzNmI1Y2UwMzZiNTEzNzdmMjRiYWI3ZGQwYzJhZjdmMTA3NDE2ZWY4NThmZjc5YjA2NzBjNzI0MDZkYWQwNjRlNzJiYjE3ZmMwYTkwMzhiYic7XG4gICAgICBjb25zdCBzZWVkID0gQnVmZmVyLmZyb20oc2VlZFRleHQsICdoZXgnKTtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBiYXNlY29pbi5nZW5lcmF0ZUtleVBhaXIoc2VlZCk7XG4gICAgICBhc3NlcnQuZXF1YWwoXG4gICAgICAgIGtleVBhaXIucHViLFxuICAgICAgICAneHB1YjY2MU15TXdBcVJiY0ZBd3F2U0diazM1a0pmN0NRcWROMXc0Q01VQkJUcUg1ZTNpdmpVNkQ4dWd2OWhSU2dSYlJlbkM0dzNhaFhkTFZhaHdqZ2pYaFN1UUtNZE5kbjU1WTlUTlNhZ0JrdHdzJ1xuICAgICAgKTtcbiAgICAgIGFzc2VydC5lcXVhbChcbiAgICAgICAga2V5UGFpci5wcnYsXG4gICAgICAgICd4cHJ2OXMyMVpyUUgxNDNLMmdzTnBRamJOdTkxa2RHaTFOdVdlaThiWjVtWnVWazZtRlBuQnZteGI3TlNKUWRiWlczRkdwSzNZY243am9yQVhjRXpNdnZpR3RieUJ6NXRCcmpmbld5UXAzZzc1RksnXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQnVpbGQgVW5zaWduZWQgU3dlZXAnLCAoKSA9PiB7XG4gICAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICAgIG1vY2sucmVzZXQoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVjb3ZlciB0cnggZnJvbSBiYXNlIGFkZHJlc3MgdG8gcmVjb3ZlcnkgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG1vY2subWV0aG9kKFRyeC5wcm90b3R5cGUgYXMgYW55LCAnZ2V0QWNjb3VudEJhbGFuY2VzRnJvbU5vZGUnLCAoLi4uYXJncykgPT4ge1xuICAgICAgICBpZiAoYXJncy5sZW5ndGggPiAwICYmIGFyZ3NbMF0gPT09IFRlc3RSZWNvdmVyRGF0YS5iYXNlQWRkcmVzcykge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoYmFzZUFkZHJlc3NCYWxhbmNlKDMwMDAwMDApKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgYmFzZUFkZHJIZXggPSBVdGlscy5nZXRIZXhBZGRyZXNzRnJvbUJhc2U1OEFkZHJlc3MoVGVzdFJlY292ZXJEYXRhLmJhc2VBZGRyZXNzKTtcbiAgICAgIGNvbnN0IGRlc3RpbmF0aW9uSGV4ID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKFRlc3RSZWNvdmVyRGF0YS5yZWNvdmVyeURlc3RpbmF0aW9uKTtcblxuICAgICAgbW9jay5tZXRob2QoVHJ4LnByb3RvdHlwZSBhcyBhbnksICdnZXRCdWlsZFRyYW5zYWN0aW9uJywgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID4gMCAmJiBhcmdzWzBdID09PSBkZXN0aW5hdGlvbkhleCAmJiBhcmdzWzFdID09PSBiYXNlQWRkckhleCAmJiBhcmdzWzJdID09PSA5MDAwMDApIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGNyZWF0aW9uVHJhbnNhY3Rpb24oYmFzZUFkZHJIZXgsIGRlc3RpbmF0aW9uSGV4LCA5MDAwMDApKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6IFRlc3RSZWNvdmVyRGF0YS51c2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXk6IFRlc3RSZWNvdmVyRGF0YS5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBUZXN0UmVjb3ZlckRhdGEuYml0Z29LZXksXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IFRlc3RSZWNvdmVyRGF0YS5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgfSk7XG4gICAgICBhc3NlcnQubm90RXF1YWwocmVzLmxlbmd0aCwgMCk7XG4gICAgICBhc3NlcnQub2soT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJlcywgJ3R4SGV4JykpO1xuICAgICAgYXNzZXJ0Lm9rKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXMsICdmZWVJbmZvJykpO1xuICAgICAgY29uc3QgcmF3RGF0YSA9IEpTT04ucGFyc2UocmVzLnR4SGV4KS5yYXdfZGF0YTtcbiAgICAgIGFzc2VydC5vayhPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmF3RGF0YSwgJ2NvbnRyYWN0JykpO1xuICAgICAgY29uc3QgdmFsdWUgPSByYXdEYXRhLmNvbnRyYWN0WzBdLnBhcmFtZXRlci52YWx1ZTtcbiAgICAgIGFzc2VydC5lcXVhbCh2YWx1ZS5hbW91bnQsIDkwMDAwMCk7XG4gICAgICBhc3NlcnQuZXF1YWwoVXRpbHMuZ2V0QmFzZTU4QWRkcmVzc0Zyb21IZXgodmFsdWUub3duZXJfYWRkcmVzcyksIFRlc3RSZWNvdmVyRGF0YS5iYXNlQWRkcmVzcyk7XG4gICAgICBhc3NlcnQuZXF1YWwoVXRpbHMuZ2V0QmFzZTU4QWRkcmVzc0Zyb21IZXgodmFsdWUudG9fYWRkcmVzcyksIFRlc3RSZWNvdmVyRGF0YS5yZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVjb3ZlciB0cnggZnJvbSBiYXNlIGFkZHJlc3MgdG8gcmVjb3ZlcnkgYWRkcmVzcyB3aXRoIHNjYW4gcGFzc2VkIGFzIHZhbGlkIGludGVnZXIgc3RyaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbW9jay5tZXRob2QoVHJ4LnByb3RvdHlwZSBhcyBhbnksICdnZXRBY2NvdW50QmFsYW5jZXNGcm9tTm9kZScsICguLi5hcmdzKSA9PiB7XG4gICAgICAgIGlmIChhcmdzLmxlbmd0aCA+IDAgJiYgYXJnc1swXSA9PT0gVGVzdFJlY292ZXJEYXRhLmJhc2VBZGRyZXNzKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShiYXNlQWRkcmVzc0JhbGFuY2UoMzAwMDAwMCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBiYXNlQWRkckhleCA9IFV0aWxzLmdldEhleEFkZHJlc3NGcm9tQmFzZTU4QWRkcmVzcyhUZXN0UmVjb3ZlckRhdGEuYmFzZUFkZHJlc3MpO1xuICAgICAgY29uc3QgZGVzdGluYXRpb25IZXggPSBVdGlscy5nZXRIZXhBZGRyZXNzRnJvbUJhc2U1OEFkZHJlc3MoVGVzdFJlY292ZXJEYXRhLnJlY292ZXJ5RGVzdGluYXRpb24pO1xuXG4gICAgICBtb2NrLm1ldGhvZChUcngucHJvdG90eXBlIGFzIGFueSwgJ2dldEJ1aWxkVHJhbnNhY3Rpb24nLCAoLi4uYXJncykgPT4ge1xuICAgICAgICBpZiAoYXJncy5sZW5ndGggPiAwICYmIGFyZ3NbMF0gPT09IGRlc3RpbmF0aW9uSGV4ICYmIGFyZ3NbMV0gPT09IGJhc2VBZGRySGV4ICYmIGFyZ3NbMl0gPT09IDkwMDAwMCkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoY3JlYXRpb25UcmFuc2FjdGlvbihiYXNlQWRkckhleCwgZGVzdGluYXRpb25IZXgsIDkwMDAwMCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogVGVzdFJlY292ZXJEYXRhLnVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogVGVzdFJlY292ZXJEYXRhLmJhY2t1cEtleSxcbiAgICAgICAgYml0Z29LZXk6IFRlc3RSZWNvdmVyRGF0YS5iaXRnb0tleSxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogVGVzdFJlY292ZXJEYXRhLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgIHNjYW46ICcxMCcsXG4gICAgICB9KTtcbiAgICAgIGFzc2VydC5ub3RFcXVhbChyZXMubGVuZ3RoLCAwKTtcbiAgICAgIGFzc2VydC5vayhPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmVzLCAndHhIZXgnKSk7XG4gICAgICBhc3NlcnQub2soT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJlcywgJ2ZlZUluZm8nKSk7XG4gICAgICBjb25zdCByYXdEYXRhID0gSlNPTi5wYXJzZShyZXMudHhIZXgpLnJhd19kYXRhO1xuICAgICAgYXNzZXJ0Lm9rKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyYXdEYXRhLCAnY29udHJhY3QnKSk7XG4gICAgICBjb25zdCB2YWx1ZSA9IHJhd0RhdGEuY29udHJhY3RbMF0ucGFyYW1ldGVyLnZhbHVlO1xuICAgICAgYXNzZXJ0LmVxdWFsKHZhbHVlLmFtb3VudCwgOTAwMDAwKTtcbiAgICAgIGFzc2VydC5lcXVhbChVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleCh2YWx1ZS5vd25lcl9hZGRyZXNzKSwgVGVzdFJlY292ZXJEYXRhLmJhc2VBZGRyZXNzKTtcbiAgICAgIGFzc2VydC5lcXVhbChVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleCh2YWx1ZS50b19hZGRyZXNzKSwgVGVzdFJlY292ZXJEYXRhLnJlY292ZXJ5RGVzdGluYXRpb24pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHJlY292ZXIgdHJ4IGZyb20gYmFzZSBhZGRyZXNzIHRvIHJlY292ZXJ5IGFkZHJlc3Mgd2l0aCBzY2FuIHBhc3NlZCBhcyB2YWxpZCBpbnRlZ2VyIHN0cmluZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG1vY2subWV0aG9kKFRyeC5wcm90b3R5cGUgYXMgYW55LCAnZ2V0QWNjb3VudEJhbGFuY2VzRnJvbU5vZGUnLCAoLi4uYXJncykgPT4ge1xuICAgICAgICBpZiAoYXJncy5sZW5ndGggPiAwICYmIGFyZ3NbMF0gPT09IFRlc3RSZWNvdmVyRGF0YS5iYXNlQWRkcmVzcykge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoYmFzZUFkZHJlc3NCYWxhbmNlKDMwMDAwMDApKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgYmFzZUFkZHJIZXggPSBVdGlscy5nZXRIZXhBZGRyZXNzRnJvbUJhc2U1OEFkZHJlc3MoVGVzdFJlY292ZXJEYXRhLmJhc2VBZGRyZXNzKTtcbiAgICAgIGNvbnN0IGRlc3RpbmF0aW9uSGV4ID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKFRlc3RSZWNvdmVyRGF0YS5yZWNvdmVyeURlc3RpbmF0aW9uKTtcblxuICAgICAgbW9jay5tZXRob2QoVHJ4LnByb3RvdHlwZSBhcyBhbnksICdnZXRCdWlsZFRyYW5zYWN0aW9uJywgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID4gMCAmJiBhcmdzWzBdID09PSBkZXN0aW5hdGlvbkhleCAmJiBhcmdzWzFdID09PSBiYXNlQWRkckhleCAmJiBhcmdzWzJdID09PSA5MDAwMDApIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGNyZWF0aW9uVHJhbnNhY3Rpb24oYmFzZUFkZHJIZXgsIGRlc3RpbmF0aW9uSGV4LCA5MDAwMDApKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgIGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgIHVzZXJLZXk6IFRlc3RSZWNvdmVyRGF0YS51c2VyS2V5LFxuICAgICAgICAgIGJhY2t1cEtleTogVGVzdFJlY292ZXJEYXRhLmJhY2t1cEtleSxcbiAgICAgICAgICBiaXRnb0tleTogVGVzdFJlY292ZXJEYXRhLmJpdGdvS2V5LFxuICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IFRlc3RSZWNvdmVyRGF0YS5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICAgIHNjYW46ICdhYmMnLFxuICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIG1lc3NhZ2U6ICdJbnZhbGlkIHNjYW5uaW5nIGZhY3RvcicsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgdHJ4IGZyb20gcmVjZWl2ZSBhZGRyZXNzIHRvIGJhc2UgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG1vY2subWV0aG9kKFRyeC5wcm90b3R5cGUgYXMgYW55LCAnZ2V0QWNjb3VudEJhbGFuY2VzRnJvbU5vZGUnLCAoLi4uYXJncykgPT4ge1xuICAgICAgICBpZiAoYXJncy5sZW5ndGggPiAwICYmIGFyZ3NbMF0gPT09IFRlc3RSZWNvdmVyRGF0YS5iYXNlQWRkcmVzcykge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoYmFzZUFkZHJlc3NCYWxhbmNlKDIwMDAwMDApKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhcmdzLmxlbmd0aCA+IDAgJiYgYXJnc1swXSA9PT0gVGVzdFJlY292ZXJEYXRhLmZpcnN0UmVjZWl2ZUFkZHJlc3MpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlY2VpdmVBZGRyZXNzQmFsYW5jZSgxMDIxMDAwMDAsIFRlc3RSZWNvdmVyRGF0YS5maXJzdFJlY2VpdmVBZGRyZXNzKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGZpcnN0UmVjZWl2ZUFkZHJlc3NIZXggPSBVdGlscy5nZXRIZXhBZGRyZXNzRnJvbUJhc2U1OEFkZHJlc3MoVGVzdFJlY292ZXJEYXRhLmZpcnN0UmVjZWl2ZUFkZHJlc3MpO1xuICAgICAgY29uc3QgYmFzZUFkZHJIZXggPSBVdGlscy5nZXRIZXhBZGRyZXNzRnJvbUJhc2U1OEFkZHJlc3MoVGVzdFJlY292ZXJEYXRhLmJhc2VBZGRyZXNzKTtcblxuICAgICAgbW9jay5tZXRob2QoVHJ4LnByb3RvdHlwZSBhcyBhbnksICdnZXRCdWlsZFRyYW5zYWN0aW9uJywgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID4gMCAmJiBhcmdzWzBdID09PSBiYXNlQWRkckhleCAmJiBhcmdzWzFdID09PSBmaXJzdFJlY2VpdmVBZGRyZXNzSGV4ICYmIGFyZ3NbMl0gPT09IDEwMDAwMDAwMCkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoY3JlYXRpb25UcmFuc2FjdGlvbihmaXJzdFJlY2VpdmVBZGRyZXNzSGV4LCBiYXNlQWRkckhleCwgMTAwMDAwMDAwKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiBUZXN0UmVjb3ZlckRhdGEudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBUZXN0UmVjb3ZlckRhdGEuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogVGVzdFJlY292ZXJEYXRhLmJpdGdvS2V5LFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBUZXN0UmVjb3ZlckRhdGEucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgIH0pO1xuICAgICAgYXNzZXJ0Lm5vdEVxdWFsKHJlcy5sZW5ndGgsIDApO1xuICAgICAgYXNzZXJ0Lm9rKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXMsICd0eEhleCcpKTtcbiAgICAgIGFzc2VydC5vayhPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmVzLCAnZmVlSW5mbycpKTtcbiAgICAgIGNvbnN0IHJhd0RhdGEgPSBKU09OLnBhcnNlKHJlcy50eEhleCkucmF3X2RhdGE7XG4gICAgICBhc3NlcnQub2soT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJhd0RhdGEsICdjb250cmFjdCcpKTtcbiAgICAgIGNvbnN0IHZhbHVlID0gcmF3RGF0YS5jb250cmFjdFswXS5wYXJhbWV0ZXIudmFsdWU7XG4gICAgICBhc3NlcnQuZXF1YWwodmFsdWUuYW1vdW50LCAxMDAwMDAwMDApO1xuICAgICAgYXNzZXJ0LmVxdWFsKFV0aWxzLmdldEJhc2U1OEFkZHJlc3NGcm9tSGV4KHZhbHVlLm93bmVyX2FkZHJlc3MpLCBUZXN0UmVjb3ZlckRhdGEuZmlyc3RSZWNlaXZlQWRkcmVzcyk7XG4gICAgICBhc3NlcnQuZXF1YWwoVXRpbHMuZ2V0QmFzZTU4QWRkcmVzc0Zyb21IZXgodmFsdWUudG9fYWRkcmVzcyksIFRlc3RSZWNvdmVyRGF0YS5iYXNlQWRkcmVzcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgdG9rZW4gZnJvbSBiYXNlIGFkZHJlc3MgdG8gcmVjb3ZlcnkgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG1vY2subWV0aG9kKFRyeC5wcm90b3R5cGUgYXMgYW55LCAnZ2V0QWNjb3VudEJhbGFuY2VzRnJvbU5vZGUnLCAoLi4uYXJncykgPT4ge1xuICAgICAgICBpZiAoYXJncy5sZW5ndGggPiAwICYmIGFyZ3NbMF0gPT09IFRlc3RSZWNvdmVyRGF0YS5iYXNlQWRkcmVzcykge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoXG4gICAgICAgICAgICBiYXNlQWRkcmVzc0JhbGFuY2UoMTAwMDAwMDAwLCBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBUU2Rad05xcEhvZnpQNkJzQktHUVVXZEJlSnBoTG1GNmlkOiAnMTAwMDAwMDAwMCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBURzNYWHlFeEJrUHA5bnpkYWpEWnNvekV1NEJrYVNKb3pzOiAnMTEwMDAwMDAwMCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSk7XG5cbiAgICAgIG1vY2subWV0aG9kKFRyeC5wcm90b3R5cGUgYXMgYW55LCAnZ2V0VHJpZ2dlclNtYXJ0Q29udHJhY3RUcmFuc2FjdGlvbicsICguLi5hcmdzKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoU2FtcGxlUmF3VG9rZW5TZW5kVHhuKTtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogVGVzdFJlY292ZXJEYXRhLnVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogVGVzdFJlY292ZXJEYXRhLmJhY2t1cEtleSxcbiAgICAgICAgYml0Z29LZXk6IFRlc3RSZWNvdmVyRGF0YS5iaXRnb0tleSxcbiAgICAgICAgdG9rZW5Db250cmFjdEFkZHJlc3M6ICdURzNYWHlFeEJrUHA5bnpkYWpEWnNvekV1NEJrYVNKb3pzJyxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogVGVzdFJlY292ZXJEYXRhLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICB9KTtcbiAgICAgIGFzc2VydC5ub3RFcXVhbChyZXMubGVuZ3RoLCAwKTtcbiAgICAgIGFzc2VydC5lcXVhbChyZXMucmVjb3ZlcnlBbW91bnQsIDExMDAwMDAwMDApO1xuICAgICAgYXNzZXJ0LmVxdWFsKHJlcy5mZWVJbmZvLmZlZSwgJzEwMDAwMDAwMCcpO1xuICAgICAgY29uc3QgZXhwaXJhdGlvbkR1cmF0aW9uID0gcmVzLnR4LnJhd19kYXRhLmV4cGlyYXRpb24gLSByZXMudHgucmF3X2RhdGEudGltZXN0YW1wO1xuICAgICAgYXNzZXJ0Lm9rKGV4cGlyYXRpb25EdXJhdGlvbiA+PSA4NjQwMDAwMCk7XG4gICAgICBhc3NlcnQuZXF1YWwocmVzLmFkZHJlc3NJbmZvLCB1bmRlZmluZWQpO1xuICAgICAgY29uc3QgcmF3RGF0YSA9IEpTT04ucGFyc2UocmVzLnR4SGV4KS5yYXdfZGF0YTtcbiAgICAgIGFzc2VydC5vayhPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmF3RGF0YSwgJ2NvbnRyYWN0JykpO1xuICAgICAgY29uc3QgdmFsdWUgPSByYXdEYXRhLmNvbnRyYWN0WzBdLnBhcmFtZXRlci52YWx1ZTtcbiAgICAgIGFzc2VydC5lcXVhbChVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleCh2YWx1ZS5vd25lcl9hZGRyZXNzKSwgVGVzdFJlY292ZXJEYXRhLmJhc2VBZGRyZXNzKTtcbiAgICAgIGFzc2VydC5lcXVhbChVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleCh2YWx1ZS5jb250cmFjdF9hZGRyZXNzKSwgJ1RHM1hYeUV4QmtQcDluemRhakRac296RXU0QmthU0pvenMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgdHJ4IGJhbGFuY2UgYXQgYmFzZSBhZGRyZXNzIGlzIG5vdCBzdWZmaWNpZW50IHRvIGNvdmVyIHRva2VuIHNlbmQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBtb2NrLm1ldGhvZChUcngucHJvdG90eXBlIGFzIGFueSwgJ2dldEFjY291bnRCYWxhbmNlc0Zyb21Ob2RlJywgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID4gMCAmJiBhcmdzWzBdID09PSBUZXN0UmVjb3ZlckRhdGEuYmFzZUFkZHJlc3MpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICAgICAgYmFzZUFkZHJlc3NCYWxhbmNlKDEwMDAwMDAsIFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIFRHM1hYeUV4QmtQcDluemRhakRac296RXU0QmthU0pvenM6ICcxMTAwMDAwMDAwJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0pXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9KTtcblxuICAgICAgbW9jay5tZXRob2QoVHJ4LnByb3RvdHlwZSBhcyBhbnksICdnZXRUcmlnZ2VyU21hcnRDb250cmFjdFRyYW5zYWN0aW9uJywgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShTYW1wbGVSYXdUb2tlblNlbmRUeG4pO1xuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiBUZXN0UmVjb3ZlckRhdGEudXNlcktleSxcbiAgICAgICAgICBiYWNrdXBLZXk6IFRlc3RSZWNvdmVyRGF0YS5iYWNrdXBLZXksXG4gICAgICAgICAgYml0Z29LZXk6IFRlc3RSZWNvdmVyRGF0YS5iaXRnb0tleSxcbiAgICAgICAgICB0b2tlbkNvbnRyYWN0QWRkcmVzczogJ1RHM1hYeUV4QmtQcDluemRhakRac296RXU0QmthU0pvenMnLFxuICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IFRlc3RSZWNvdmVyRGF0YS5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIG1lc3NhZ2U6XG4gICAgICAgICAgICBcIkFtb3VudCBvZiBmdW5kcyB0byByZWNvdmVyIDEwMDAwMDAgaXMgbGVzcyB0aGFuIDEwMDAwMDAwMCBhbmQgd291bGRuJ3QgYmUgYWJsZSB0byBmdW5kIGEgdHJjMjAgc2VuZFwiLFxuICAgICAgICB9XG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQnVpbGQgVW5zaWduZWQgQ29uc29saWRhdGlvbiBSZWNvdmVyaWVzJywgKCkgPT4ge1xuICAgIGFmdGVyRWFjaCgoKSA9PiB7XG4gICAgICBtb2NrLnJlc2V0KCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGlmIHN0YXJ0aW5nU2NhbkluZGV4IGlzIG5vdCBnZSB0byAxJywgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgIGJhc2Vjb2luLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgICAgdXNlcktleTogVGVzdFJlY292ZXJEYXRhLnVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5OiBUZXN0UmVjb3ZlckRhdGEuYmFja3VwS2V5LFxuICAgICAgICAgIGJpdGdvS2V5OiBUZXN0UmVjb3ZlckRhdGEuYml0Z29LZXksXG4gICAgICAgICAgc3RhcnRpbmdTY2FuSW5kZXg6IC0xLFxuICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIG1lc3NhZ2U6XG4gICAgICAgICAgICAnSW52YWxpZCBzdGFydGluZyBvciBlbmRpbmcgaW5kZXggdG8gc2NhbiBmb3IgYWRkcmVzc2VzLiBzdGFydGluZ1NjYW5JbmRleDogLTEsIGVuZGluZ1NjYW5JbmRleDogMTkuJyxcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgc2NhbiBmYWN0b3IgaXMgdG9vIGhpZ2gnLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgYmFzZWNvaW4ucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgICB1c2VyS2V5OiBUZXN0UmVjb3ZlckRhdGEudXNlcktleSxcbiAgICAgICAgICBiYWNrdXBLZXk6IFRlc3RSZWNvdmVyRGF0YS5iYWNrdXBLZXksXG4gICAgICAgICAgYml0Z29LZXk6IFRlc3RSZWNvdmVyRGF0YS5iaXRnb0tleSxcbiAgICAgICAgICBzdGFydGluZ1NjYW5JbmRleDogMSxcbiAgICAgICAgICBlbmRpbmdTY2FuSW5kZXg6IDMwMCxcbiAgICAgICAgfSksXG4gICAgICAgIHtcbiAgICAgICAgICBtZXNzYWdlOlxuICAgICAgICAgICAgJ0ludmFsaWQgc3RhcnRpbmcgb3IgZW5kaW5nIGluZGV4IHRvIHNjYW4gZm9yIGFkZHJlc3Nlcy4gc3RhcnRpbmdTY2FuSW5kZXg6IDEsIGVuZGluZ1NjYW5JbmRleDogMzAwLicsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGNvbnNvbGlkYXRlIHJlY292ZXJpZXMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBtb2NrLm1ldGhvZChUcngucHJvdG90eXBlIGFzIGFueSwgJ2dldEFjY291bnRCYWxhbmNlc0Zyb21Ob2RlJywgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID4gMCAmJiBhcmdzWzBdID09PSBUZXN0UmVjb3ZlckRhdGEuZmlyc3RSZWNlaXZlQWRkcmVzcykge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVjZWl2ZUFkZHJlc3NCYWxhbmNlKDEwMjEwMDAwMCwgVGVzdFJlY292ZXJEYXRhLmZpcnN0UmVjZWl2ZUFkZHJlc3MpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhcmdzLmxlbmd0aCA+IDAgJiYgYXJnc1swXSA9PT0gVGVzdFJlY292ZXJEYXRhLnNlY29uZFJlY2VpdmVBZGRyZXNzKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZWNlaXZlQWRkcmVzc0JhbGFuY2UoNTAwMDAwMDAsIFRlc3RSZWNvdmVyRGF0YS5zZWNvbmRSZWNlaXZlQWRkcmVzcykpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0pO1xuXG4gICAgICBtb2NrLm1ldGhvZChUcngucHJvdG90eXBlIGFzIGFueSwgJ2dldEJ1aWxkVHJhbnNhY3Rpb24nLCAoLi4uYXJncykgPT4ge1xuICAgICAgICBpZiAoYXJncy5sZW5ndGggPiAwICYmIGFyZ3NbMF0gPT09IGJhc2VBZGRySGV4ICYmIGFyZ3NbMV0gPT09IGZpcnN0UmVjZWl2ZUFkZHJIZXggJiYgYXJnc1syXSA9PT0gMTAwMDAwMDAwKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShjcmVhdGlvblRyYW5zYWN0aW9uKGZpcnN0UmVjZWl2ZUFkZHJIZXgsIGJhc2VBZGRySGV4LCAxMDAwMDAwMDApKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhcmdzLmxlbmd0aCA+IDAgJiYgYXJnc1swXSA9PT0gYmFzZUFkZHJIZXggJiYgYXJnc1sxXSA9PT0gc2Vjb25kUmVjZWl2ZUFkZHJIZXggJiYgYXJnc1syXSA9PT0gNDc5MDAwMDApIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGNyZWF0aW9uVHJhbnNhY3Rpb24oc2Vjb25kUmVjZWl2ZUFkZHJIZXgsIGJhc2VBZGRySGV4LCA0NzkwMDAwMCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBmaXJzdFJlY2VpdmVBZGRySGV4ID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKFRlc3RSZWNvdmVyRGF0YS5maXJzdFJlY2VpdmVBZGRyZXNzKTtcbiAgICAgIGNvbnN0IHNlY29uZFJlY2VpdmVBZGRySGV4ID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKFRlc3RSZWNvdmVyRGF0YS5zZWNvbmRSZWNlaXZlQWRkcmVzcyk7XG4gICAgICBjb25zdCBiYXNlQWRkckhleCA9IFV0aWxzLmdldEhleEFkZHJlc3NGcm9tQmFzZTU4QWRkcmVzcyhUZXN0UmVjb3ZlckRhdGEuYmFzZUFkZHJlc3MpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyQ29uc29saWRhdGlvbnMoe1xuICAgICAgICB1c2VyS2V5OiBUZXN0UmVjb3ZlckRhdGEudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBUZXN0UmVjb3ZlckRhdGEuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogVGVzdFJlY292ZXJEYXRhLmJpdGdvS2V5LFxuICAgICAgICBzdGFydGluZ1NjYW5JbmRleDogMSxcbiAgICAgICAgZW5kaW5nU2NhbkluZGV4OiAzLFxuICAgICAgfSk7XG5cbiAgICAgIGFzc2VydC5ub3RFcXVhbChyZXMubGVuZ3RoLCAwKTtcbiAgICAgIGFzc2VydC5vayhPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmVzLCAndHJhbnNhY3Rpb25zJykpO1xuICAgICAgYXNzZXJ0LmVxdWFsKHJlcy50cmFuc2FjdGlvbnMubGVuZ3RoLCAyKTtcbiAgICAgIGNvbnN0IHR4bjEgPSByZXMudHJhbnNhY3Rpb25zWzBdO1xuICAgICAgY29uc3QgcmF3RGF0YTEgPSBKU09OLnBhcnNlKHR4bjEudHhIZXgpLnJhd19kYXRhO1xuICAgICAgYXNzZXJ0Lm9rKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyYXdEYXRhMSwgJ2NvbnRyYWN0JykpO1xuICAgICAgY29uc3QgdmFsdWUxID0gcmF3RGF0YTEuY29udHJhY3RbMF0ucGFyYW1ldGVyLnZhbHVlO1xuICAgICAgYXNzZXJ0LmVxdWFsKHZhbHVlMS5hbW91bnQsIDEwMDAwMDAwMCk7XG4gICAgICBhc3NlcnQuZXF1YWwoVXRpbHMuZ2V0QmFzZTU4QWRkcmVzc0Zyb21IZXgodmFsdWUxLm93bmVyX2FkZHJlc3MpLCBUZXN0UmVjb3ZlckRhdGEuZmlyc3RSZWNlaXZlQWRkcmVzcyk7XG4gICAgICBhc3NlcnQuZXF1YWwoVXRpbHMuZ2V0QmFzZTU4QWRkcmVzc0Zyb21IZXgodmFsdWUxLnRvX2FkZHJlc3MpLCBUZXN0UmVjb3ZlckRhdGEuYmFzZUFkZHJlc3MpO1xuICAgICAgY29uc3QgdHhuMiA9IHJlcy50cmFuc2FjdGlvbnNbMV07XG4gICAgICBjb25zdCByYXdEYXRhMiA9IEpTT04ucGFyc2UodHhuMi50eEhleCkucmF3X2RhdGE7XG4gICAgICBhc3NlcnQub2soT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJhd0RhdGEyLCAnY29udHJhY3QnKSk7XG4gICAgICBjb25zdCB2YWx1ZTIgPSByYXdEYXRhMi5jb250cmFjdFswXS5wYXJhbWV0ZXIudmFsdWU7XG4gICAgICBhc3NlcnQuZXF1YWwodmFsdWUyLmFtb3VudCwgNDc5MDAwMDApO1xuICAgICAgYXNzZXJ0LmVxdWFsKFV0aWxzLmdldEJhc2U1OEFkZHJlc3NGcm9tSGV4KHZhbHVlMi5vd25lcl9hZGRyZXNzKSwgVGVzdFJlY292ZXJEYXRhLnNlY29uZFJlY2VpdmVBZGRyZXNzKTtcbiAgICAgIGFzc2VydC5lcXVhbChVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleCh2YWx1ZTIudG9fYWRkcmVzcyksIFRlc3RSZWNvdmVyRGF0YS5iYXNlQWRkcmVzcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGNvbnNvbGlkYXRlIHRva2VuIHJlY292ZXJpZXMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBtb2NrLm1ldGhvZChUcngucHJvdG90eXBlIGFzIGFueSwgJ2dldEFjY291bnRCYWxhbmNlc0Zyb21Ob2RlJywgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID4gMCAmJiBhcmdzWzBdID09PSBUZXN0UmVjb3ZlckRhdGEuZmlyc3RSZWNlaXZlQWRkcmVzcykge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoXG4gICAgICAgICAgICByZWNlaXZlQWRkcmVzc0JhbGFuY2UoMjAyMTAwMDAwLCBUZXN0UmVjb3ZlckRhdGEuZmlyc3RSZWNlaXZlQWRkcmVzcywgW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgVFNkWndOcXBIb2Z6UDZCc0JLR1FVV2RCZUpwaExtRjZpZDogJzExMDAwMDAwMDAnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSlcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID4gMCAmJiBhcmdzWzBdID09PSBUZXN0UmVjb3ZlckRhdGEuc2Vjb25kUmVjZWl2ZUFkZHJlc3MpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlY2VpdmVBZGRyZXNzQmFsYW5jZSg1MDAsIFRlc3RSZWNvdmVyRGF0YS5zZWNvbmRSZWNlaXZlQWRkcmVzcykpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0pO1xuXG4gICAgICBtb2NrLm1ldGhvZChUcngucHJvdG90eXBlIGFzIGFueSwgJ2dldEJ1aWxkVHJhbnNhY3Rpb24nLCAoLi4uYXJncykgPT4ge1xuICAgICAgICBpZiAoYXJncy5sZW5ndGggPiAwICYmIGFyZ3NbMF0gPT09IGJhc2VBZGRySGV4ICYmIGFyZ3NbMV0gPT09IGZpcnN0UmVjZWl2ZUFkZHJIZXggJiYgYXJnc1syXSA9PT0gMTEwMDAwMDAwMCkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoY3JlYXRpb25UcmFuc2FjdGlvbihmaXJzdFJlY2VpdmVBZGRySGV4LCBiYXNlQWRkckhleCwgMTEwMDAwMDAwMCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBmaXJzdFJlY2VpdmVBZGRySGV4ID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKFRlc3RSZWNvdmVyRGF0YS5maXJzdFJlY2VpdmVBZGRyZXNzKTtcbiAgICAgIGNvbnN0IGJhc2VBZGRySGV4ID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKFRlc3RSZWNvdmVyRGF0YS5iYXNlQWRkcmVzcyk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgIHVzZXJLZXk6IFRlc3RSZWNvdmVyRGF0YS51c2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXk6IFRlc3RSZWNvdmVyRGF0YS5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBUZXN0UmVjb3ZlckRhdGEuYml0Z29LZXksXG4gICAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiAnVFNkWndOcXBIb2Z6UDZCc0JLR1FVV2RCZUpwaExtRjZpZCcsXG4gICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAxLFxuICAgICAgICBlbmRpbmdTY2FuSW5kZXg6IDMsXG4gICAgICB9KTtcblxuICAgICAgYXNzZXJ0Lm5vdEVxdWFsKHJlcy5sZW5ndGgsIDApO1xuICAgICAgYXNzZXJ0Lm9rKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXMsICd0cmFuc2FjdGlvbnMnKSk7XG4gICAgICBhc3NlcnQuZXF1YWwocmVzLnRyYW5zYWN0aW9ucy5sZW5ndGgsIDEpO1xuICAgICAgY29uc3QgdHhuID0gcmVzLnRyYW5zYWN0aW9uc1swXTtcbiAgICAgIGNvbnN0IHJhd0RhdGEgPSBKU09OLnBhcnNlKHR4bi50eEhleCkucmF3X2RhdGE7XG4gICAgICBhc3NlcnQub2soT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJhd0RhdGEsICdjb250cmFjdCcpKTtcbiAgICAgIGNvbnN0IHZhbHVlID0gcmF3RGF0YS5jb250cmFjdFswXS5wYXJhbWV0ZXIudmFsdWU7XG4gICAgICBhc3NlcnQuZXF1YWwoXG4gICAgICAgIHZhbHVlLmRhdGEsXG4gICAgICAgICdhOTA1OWNiYjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGMyNTQyMDI1NWMyYzVhMmRkNTRlZjY5ZjkyZWYyNjFlNmJkNDIxNmEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDQxOTBhYjAwJ1xuICAgICAgKTtcbiAgICAgIGFzc2VydC5lcXVhbChVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleCh2YWx1ZS5vd25lcl9hZGRyZXNzKSwgVGVzdFJlY292ZXJEYXRhLmZpcnN0UmVjZWl2ZUFkZHJlc3MpO1xuICAgICAgYXNzZXJ0LmVxdWFsKFV0aWxzLmdldEJhc2U1OEFkZHJlc3NGcm9tSGV4KHZhbHVlLmNvbnRyYWN0X2FkZHJlc3MpLCAnVFNkWndOcXBIb2Z6UDZCc0JLR1FVV2RCZUpwaExtRjZpZCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBza2lwIGJ1aWxkaW5nIGNvbnNvbGlkYXRlIHRyYW5zYWN0aW9uIGlmIGJhbGFuY2UgaXMgbG93ZXIgdGhhbiByZXNlcnZlZCBmZWUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBtb2NrLm1ldGhvZChUcngucHJvdG90eXBlIGFzIGFueSwgJ2dldEFjY291bnRCYWxhbmNlc0Zyb21Ob2RlJywgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID4gMCAmJiBhcmdzWzBdID09PSBUZXN0UmVjb3ZlckRhdGEuZmlyc3RSZWNlaXZlQWRkcmVzcykge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVjZWl2ZUFkZHJlc3NCYWxhbmNlKDEwMjEwMDAwMCwgVGVzdFJlY292ZXJEYXRhLmZpcnN0UmVjZWl2ZUFkZHJlc3MpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhcmdzLmxlbmd0aCA+IDAgJiYgYXJnc1swXSA9PT0gVGVzdFJlY292ZXJEYXRhLnNlY29uZFJlY2VpdmVBZGRyZXNzKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZWNlaXZlQWRkcmVzc0JhbGFuY2UoMjAwMDAwMCwgVGVzdFJlY292ZXJEYXRhLnNlY29uZFJlY2VpdmVBZGRyZXNzKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSk7XG5cbiAgICAgIG1vY2subWV0aG9kKFRyeC5wcm90b3R5cGUgYXMgYW55LCAnZ2V0QnVpbGRUcmFuc2FjdGlvbicsICguLi5hcmdzKSA9PiB7XG4gICAgICAgIGlmIChhcmdzLmxlbmd0aCA+IDAgJiYgYXJnc1swXSA9PT0gYmFzZUFkZHJIZXggJiYgYXJnc1sxXSA9PT0gZmlyc3RSZWNlaXZlQWRkckhleCAmJiBhcmdzWzJdID09PSAxMDAwMDAwMDApIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGNyZWF0aW9uVHJhbnNhY3Rpb24oZmlyc3RSZWNlaXZlQWRkckhleCwgYmFzZUFkZHJIZXgsIDEwMDAwMDAwMCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBmaXJzdFJlY2VpdmVBZGRySGV4ID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKFRlc3RSZWNvdmVyRGF0YS5maXJzdFJlY2VpdmVBZGRyZXNzKTtcbiAgICAgIGNvbnN0IGJhc2VBZGRySGV4ID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKFRlc3RSZWNvdmVyRGF0YS5iYXNlQWRkcmVzcyk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgIHVzZXJLZXk6IFRlc3RSZWNvdmVyRGF0YS51c2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXk6IFRlc3RSZWNvdmVyRGF0YS5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBUZXN0UmVjb3ZlckRhdGEuYml0Z29LZXksXG4gICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAxLFxuICAgICAgICBlbmRpbmdTY2FuSW5kZXg6IDMsXG4gICAgICB9KTtcblxuICAgICAgYXNzZXJ0Lm5vdEVxdWFsKHJlcy5sZW5ndGgsIDApO1xuICAgICAgYXNzZXJ0Lm9rKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXMsICd0cmFuc2FjdGlvbnMnKSk7XG4gICAgICBhc3NlcnQuZXF1YWwocmVzLnRyYW5zYWN0aW9ucy5sZW5ndGgsIDEpO1xuICAgICAgY29uc3QgdHhuMSA9IHJlcy50cmFuc2FjdGlvbnNbMF07XG4gICAgICBjb25zdCByYXdEYXRhMSA9IEpTT04ucGFyc2UodHhuMS50eEhleCkucmF3X2RhdGE7XG4gICAgICBhc3NlcnQub2soT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJhd0RhdGExLCAnY29udHJhY3QnKSk7XG4gICAgICBjb25zdCB2YWx1ZTEgPSByYXdEYXRhMS5jb250cmFjdFswXS5wYXJhbWV0ZXIudmFsdWU7XG4gICAgICBhc3NlcnQuZXF1YWwodmFsdWUxLmFtb3VudCwgMTAwMDAwMDAwKTtcbiAgICAgIGFzc2VydC5lcXVhbChVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleCh2YWx1ZTEub3duZXJfYWRkcmVzcyksIFRlc3RSZWNvdmVyRGF0YS5maXJzdFJlY2VpdmVBZGRyZXNzKTtcbiAgICAgIGFzc2VydC5lcXVhbChVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleCh2YWx1ZTEudG9fYWRkcmVzcyksIFRlc3RSZWNvdmVyRGF0YS5iYXNlQWRkcmVzcyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUU1MgUmVjb3ZlcnknLCAoKSA9PiB7XG4gICAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICAgIG1vY2sucmVzZXQoKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHdhbGxldEFkZHJIZXggPSBVdGlscy5nZXRIZXhBZGRyZXNzRnJvbUJhc2U1OEFkZHJlc3MoVHNzVGVzdFJlY292ZXJEYXRhLndhbGxldEFkZHJlc3MpO1xuICAgIGNvbnN0IGRlc3RpbmF0aW9uSGV4ID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKFRzc1Rlc3RSZWNvdmVyRGF0YS5yZWNvdmVyeURlc3RpbmF0aW9uKTtcblxuICAgIGl0KCdzaG91bGQgcmVjb3ZlciBUUlggZnJvbSBUU1Mgd2FsbGV0ICh1bnNpZ25lZCBzd2VlcCknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBtb2NrLm1ldGhvZChUcngucHJvdG90eXBlIGFzIGFueSwgJ2dldEFjY291bnRCYWxhbmNlc0Zyb21Ob2RlJywgKCkgPT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGJhc2VBZGRyZXNzQmFsYW5jZSgzMDAwMDAwKSk7XG4gICAgICB9KTtcblxuICAgICAgbW9jay5tZXRob2QoVHJ4LnByb3RvdHlwZSBhcyBhbnksICdnZXRCdWlsZFRyYW5zYWN0aW9uJywgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgaWYgKGFyZ3NbMF0gPT09IGRlc3RpbmF0aW9uSGV4ICYmIGFyZ3NbMV0gPT09IHdhbGxldEFkZHJIZXggJiYgYXJnc1syXSA9PT0gOTAwMDAwKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShjcmVhdGlvblRyYW5zYWN0aW9uKHdhbGxldEFkZHJIZXgsIGRlc3RpbmF0aW9uSGV4LCA5MDAwMDApKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiBUc3NUZXN0UmVjb3ZlckRhdGEudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBUc3NUZXN0UmVjb3ZlckRhdGEuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogVHNzVGVzdFJlY292ZXJEYXRhLmJpdGdvS2V5LFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBUc3NUZXN0UmVjb3ZlckRhdGEucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgaXNUc3M6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgYXNzZXJ0Lm9rKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXMsICd0eEhleCcpKTtcbiAgICAgIGFzc2VydC5vayhPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmVzLCAnZmVlSW5mbycpKTtcbiAgICAgIGFzc2VydC5lcXVhbChyZXMucmVjb3ZlcnlBbW91bnQsIDkwMDAwMCk7XG4gICAgICBjb25zdCByYXdEYXRhID0gSlNPTi5wYXJzZShyZXMudHhIZXgpLnJhd19kYXRhO1xuICAgICAgYXNzZXJ0Lm9rKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyYXdEYXRhLCAnY29udHJhY3QnKSk7XG4gICAgICBjb25zdCB2YWx1ZSA9IHJhd0RhdGEuY29udHJhY3RbMF0ucGFyYW1ldGVyLnZhbHVlO1xuICAgICAgYXNzZXJ0LmVxdWFsKHZhbHVlLmFtb3VudCwgOTAwMDAwKTtcbiAgICAgIGFzc2VydC5lcXVhbChVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleCh2YWx1ZS5vd25lcl9hZGRyZXNzKSwgVHNzVGVzdFJlY292ZXJEYXRhLndhbGxldEFkZHJlc3MpO1xuICAgICAgYXNzZXJ0LmVxdWFsKFV0aWxzLmdldEJhc2U1OEFkZHJlc3NGcm9tSGV4KHZhbHVlLnRvX2FkZHJlc3MpLCBUc3NUZXN0UmVjb3ZlckRhdGEucmVjb3ZlcnlEZXN0aW5hdGlvbik7XG4gICAgICAvLyB1bnNpZ25lZCBzd2VlcDogbm8gc2lnbmF0dXJlc1xuICAgICAgY29uc3Qgc2lnID0gSlNPTi5wYXJzZShyZXMudHhIZXgpLnNpZ25hdHVyZTtcbiAgICAgIGFzc2VydC5vayghc2lnIHx8IHNpZy5sZW5ndGggPT09IDApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvdmVyIFRSWCBmcm9tIFRTUyB3YWxsZXQgKHNpZ25lZCByZWNvdmVyeSknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBtb2NrLm1ldGhvZChUcngucHJvdG90eXBlIGFzIGFueSwgJ2dldEFjY291bnRCYWxhbmNlc0Zyb21Ob2RlJywgKCkgPT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGJhc2VBZGRyZXNzQmFsYW5jZSgzMDAwMDAwKSk7XG4gICAgICB9KTtcblxuICAgICAgbW9jay5tZXRob2QoVHJ4LnByb3RvdHlwZSBhcyBhbnksICdnZXRCdWlsZFRyYW5zYWN0aW9uJywgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgaWYgKGFyZ3NbMF0gPT09IGRlc3RpbmF0aW9uSGV4ICYmIGFyZ3NbMV0gPT09IHdhbGxldEFkZHJIZXggJiYgYXJnc1syXSA9PT0gOTAwMDAwKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShjcmVhdGlvblRyYW5zYWN0aW9uKHdhbGxldEFkZHJIZXgsIGRlc3RpbmF0aW9uSGV4LCA5MDAwMDApKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSk7XG5cbiAgICAgIG1vY2subWV0aG9kKGJpdGdvIGFzIGFueSwgJ2RlY3J5cHQnLCAoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoVHNzVGVzdFJlY292ZXJEYXRhLnVzZXJQcnZLZXkpO1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiBUc3NUZXN0UmVjb3ZlckRhdGEuZW5jcnlwdGVkVXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBUc3NUZXN0UmVjb3ZlckRhdGEuZW5jcnlwdGVkVXNlcktleSxcbiAgICAgICAgYml0Z29LZXk6IFRzc1Rlc3RSZWNvdmVyRGF0YS5iaXRnb0tleSxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogVHNzVGVzdFJlY292ZXJEYXRhLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IFRzc1Rlc3RSZWNvdmVyRGF0YS53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICBpc1RzczogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICBhc3NlcnQub2soT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJlcywgJ3R4SGV4JykpO1xuICAgICAgYXNzZXJ0Lm9rKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXMsICdmZWVJbmZvJykpO1xuICAgICAgYXNzZXJ0LmVxdWFsKHJlcy5yZWNvdmVyeUFtb3VudCwgOTAwMDAwKTtcbiAgICAgIGNvbnN0IHJhd0RhdGEgPSBKU09OLnBhcnNlKHJlcy50eEhleCkucmF3X2RhdGE7XG4gICAgICBjb25zdCB2YWx1ZSA9IHJhd0RhdGEuY29udHJhY3RbMF0ucGFyYW1ldGVyLnZhbHVlO1xuICAgICAgYXNzZXJ0LmVxdWFsKHZhbHVlLmFtb3VudCwgOTAwMDAwKTtcbiAgICAgIGFzc2VydC5lcXVhbChVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleCh2YWx1ZS5vd25lcl9hZGRyZXNzKSwgVHNzVGVzdFJlY292ZXJEYXRhLndhbGxldEFkZHJlc3MpO1xuICAgICAgYXNzZXJ0LmVxdWFsKFV0aWxzLmdldEJhc2U1OEFkZHJlc3NGcm9tSGV4KHZhbHVlLnRvX2FkZHJlc3MpLCBUc3NUZXN0UmVjb3ZlckRhdGEucmVjb3ZlcnlEZXN0aW5hdGlvbik7XG4gICAgICAvLyBzaWduZWQgcmVjb3Zlcnk6IHNob3VsZCBoYXZlIGV4YWN0bHkgMSBzaWduYXR1cmVcbiAgICAgIGNvbnN0IHNpZyA9IEpTT04ucGFyc2UocmVzLnR4SGV4KS5zaWduYXR1cmU7XG4gICAgICBhc3NlcnQuZXF1YWwoc2lnLmxlbmd0aCwgMSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgVFJDLTIwIHRva2VuIGZyb20gVFNTIHdhbGxldCAodW5zaWduZWQgc3dlZXApJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbW9jay5tZXRob2QoVHJ4LnByb3RvdHlwZSBhcyBhbnksICdnZXRBY2NvdW50QmFsYW5jZXNGcm9tTm9kZScsICgpID0+IHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShcbiAgICAgICAgICBiYXNlQWRkcmVzc0JhbGFuY2UoMTAwMDAwMDAwLCBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIFRHM1hYeUV4QmtQcDluemRhakRac296RXU0QmthU0pvenM6ICcxMTAwMDAwMDAwJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBtb2NrLm1ldGhvZChUcngucHJvdG90eXBlIGFzIGFueSwgJ2dldFRyaWdnZXJTbWFydENvbnRyYWN0VHJhbnNhY3Rpb24nLCAoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoU2FtcGxlUmF3VG9rZW5TZW5kVHhuKTtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogVHNzVGVzdFJlY292ZXJEYXRhLnVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogVHNzVGVzdFJlY292ZXJEYXRhLmJhY2t1cEtleSxcbiAgICAgICAgYml0Z29LZXk6IFRzc1Rlc3RSZWNvdmVyRGF0YS5iaXRnb0tleSxcbiAgICAgICAgdG9rZW5Db250cmFjdEFkZHJlc3M6ICdURzNYWHlFeEJrUHA5bnpkYWpEWnNvekV1NEJrYVNKb3pzJyxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogVHNzVGVzdFJlY292ZXJEYXRhLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgIGlzVHNzOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIGFzc2VydC5vayhPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmVzLCAndHhIZXgnKSk7XG4gICAgICBhc3NlcnQuZXF1YWwocmVzLnJlY292ZXJ5QW1vdW50LCAxMTAwMDAwMDAwKTtcbiAgICAgIGFzc2VydC5lcXVhbChyZXMuZmVlSW5mby5mZWUsICcxMDAwMDAwMDAnKTtcbiAgICAgIGNvbnN0IGV4cGlyYXRpb25EdXJhdGlvbiA9IHJlcy50eC5yYXdfZGF0YS5leHBpcmF0aW9uIC0gcmVzLnR4LnJhd19kYXRhLnRpbWVzdGFtcDtcbiAgICAgIGFzc2VydC5vayhleHBpcmF0aW9uRHVyYXRpb24gPj0gODY0MDAwMDApO1xuICAgICAgLy8gdW5zaWduZWQgc3dlZXA6IG5vIHNpZ25hdHVyZXNcbiAgICAgIGNvbnN0IHNpZyA9IEpTT04ucGFyc2UocmVzLnR4SGV4KS5zaWduYXR1cmU7XG4gICAgICBhc3NlcnQub2soIXNpZyB8fCBzaWcubGVuZ3RoID09PSAwKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVjb3ZlciBUUkMtMjAgdG9rZW4gZnJvbSBUU1Mgd2FsbGV0IChzaWduZWQgcmVjb3ZlcnkpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbW9jay5tZXRob2QoVHJ4LnByb3RvdHlwZSBhcyBhbnksICdnZXRBY2NvdW50QmFsYW5jZXNGcm9tTm9kZScsICgpID0+IHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShcbiAgICAgICAgICBiYXNlQWRkcmVzc0JhbGFuY2UoMTAwMDAwMDAwLCBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIFRHM1hYeUV4QmtQcDluemRhakRac296RXU0QmthU0pvenM6ICcxMTAwMDAwMDAwJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBtb2NrLm1ldGhvZChUcngucHJvdG90eXBlIGFzIGFueSwgJ2dldFRyaWdnZXJTbWFydENvbnRyYWN0VHJhbnNhY3Rpb24nLCAoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoU2FtcGxlUmF3VG9rZW5TZW5kVHhuKTtcbiAgICAgIH0pO1xuXG4gICAgICBtb2NrLm1ldGhvZChiaXRnbyBhcyBhbnksICdkZWNyeXB0JywgKCkgPT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKFRzc1Rlc3RSZWNvdmVyRGF0YS51c2VyUHJ2S2V5KTtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogVHNzVGVzdFJlY292ZXJEYXRhLmVuY3J5cHRlZFVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogVHNzVGVzdFJlY292ZXJEYXRhLmVuY3J5cHRlZFVzZXJLZXksXG4gICAgICAgIGJpdGdvS2V5OiBUc3NUZXN0UmVjb3ZlckRhdGEuYml0Z29LZXksXG4gICAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiAnVEczWFh5RXhCa1BwOW56ZGFqRFpzb3pFdTRCa2FTSm96cycsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IFRzc1Rlc3RSZWNvdmVyRGF0YS5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBUc3NUZXN0UmVjb3ZlckRhdGEud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgaXNUc3M6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgYXNzZXJ0Lm9rKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXMsICd0eEhleCcpKTtcbiAgICAgIGFzc2VydC5lcXVhbChyZXMucmVjb3ZlcnlBbW91bnQsIDExMDAwMDAwMDApO1xuICAgICAgYXNzZXJ0LmVxdWFsKHJlcy5mZWVJbmZvLmZlZSwgJzEwMDAwMDAwMCcpO1xuICAgICAgLy8gc2lnbmVkIHJlY292ZXJ5OiBzaG91bGQgaGF2ZSBleGFjdGx5IDEgc2lnbmF0dXJlXG4gICAgICBjb25zdCBzaWcgPSBKU09OLnBhcnNlKHJlcy50eEhleCkuc2lnbmF0dXJlO1xuICAgICAgYXNzZXJ0LmVxdWFsKHNpZy5sZW5ndGgsIDEpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiBUU1Mgd2FsbGV0IGhhcyBpbnN1ZmZpY2llbnQgYmFsYW5jZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG1vY2subWV0aG9kKFRyeC5wcm90b3R5cGUgYXMgYW55LCAnZ2V0QWNjb3VudEJhbGFuY2VzRnJvbU5vZGUnLCAoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoYmFzZUFkZHJlc3NCYWxhbmNlKDEwMDAwMDApKTsgLy8gbGVzcyB0aGFuIFNBRkVfVFJPTl9UUkFOU0FDVElPTl9GRUUgKDIuMWU2KVxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiBUc3NUZXN0UmVjb3ZlckRhdGEudXNlcktleSxcbiAgICAgICAgICBiYWNrdXBLZXk6IFRzc1Rlc3RSZWNvdmVyRGF0YS5iYWNrdXBLZXksXG4gICAgICAgICAgYml0Z29LZXk6IFRzc1Rlc3RSZWNvdmVyRGF0YS5iaXRnb0tleSxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBUc3NUZXN0UmVjb3ZlckRhdGEucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICBpc1RzczogdHJ1ZSxcbiAgICAgICAgfSksXG4gICAgICAgIHtcbiAgICAgICAgICBtZXNzYWdlOiBcIkFtb3VudCBvZiBmdW5kcyB0byByZWNvdmVyIDEwMDAwMDAgaXMgbGVzcyB0aGFuIDIxMDAwMDAgYW5kIHdvdWxkbid0IGJlIGFibGUgdG8gZnVuZCBhIHNlbmRcIixcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgVFJDLTIwIHRva2VuIG5vdCBmb3VuZCBmb3IgVFNTIHdhbGxldCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG1vY2subWV0aG9kKFRyeC5wcm90b3R5cGUgYXMgYW55LCAnZ2V0QWNjb3VudEJhbGFuY2VzRnJvbU5vZGUnLCAoKSA9PiB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoYmFzZUFkZHJlc3NCYWxhbmNlKDEwMDAwMDAwMCwgW10pKTtcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgdXNlcktleTogVHNzVGVzdFJlY292ZXJEYXRhLnVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5OiBUc3NUZXN0UmVjb3ZlckRhdGEuYmFja3VwS2V5LFxuICAgICAgICAgIGJpdGdvS2V5OiBUc3NUZXN0UmVjb3ZlckRhdGEuYml0Z29LZXksXG4gICAgICAgICAgdG9rZW5Db250cmFjdEFkZHJlc3M6ICdURzNYWHlFeEJrUHA5bnpkYWpEWnNvekV1NEJrYVNKb3pzJyxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBUc3NUZXN0UmVjb3ZlckRhdGEucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICBpc1RzczogdHJ1ZSxcbiAgICAgICAgfSksXG4gICAgICAgIEVycm9yTm9JbnB1dFRvUmVjb3ZlclxuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JlY292ZXIgUHJvdmlkZXIgRmFpbHVyZScsICgpID0+IHtcbiAgICBhZnRlckVhY2goKCkgPT4ge1xuICAgICAgbW9jay5yZXNldCgpO1xuICAgICAgbm9jay5jbGVhbkFsbCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBSZWNvdmVyeVByb3ZpZGVyRXJyb3Igd2hlbiB0aGUgVHJvbiBub2RlIGlzIHVucmVhY2hhYmxlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgbm9jaygnaHR0cHM6Ly9hcGkuc2hhc3RhLnRyb25ncmlkLmlvJylcbiAgICAgICAgLmdldCgvXFwvdjFcXC9hY2NvdW50c1xcLy4qLylcbiAgICAgICAgLnJlcGx5KDUwMCwgeyBlcnJvcjogJ25vZGUgdW5hdmFpbGFibGUnIH0pO1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgdXNlcktleTogVGVzdFJlY292ZXJEYXRhLnVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5OiBUZXN0UmVjb3ZlckRhdGEuYmFja3VwS2V5LFxuICAgICAgICAgIGJpdGdvS2V5OiBUZXN0UmVjb3ZlckRhdGEuYml0Z29LZXksXG4gICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogVGVzdFJlY292ZXJEYXRhLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgIH0pLFxuICAgICAgICBSZWNvdmVyeVByb3ZpZGVyRXJyb3JcbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdpc1dhbGxldEFkZHJlc3MnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgcm9vdCBhZGRyZXNzIChpbmRleCAwKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3RXYWxsZXREYXRhLnJvb3RBZGRyZXNzLFxuICAgICAgICBrZXljaGFpbnM6IHRlc3RXYWxsZXREYXRhLmtleWNoYWlucyxcbiAgICAgICAgaW5kZXg6IDAsXG4gICAgICB9KTtcbiAgICAgIGFzc2VydC5lcXVhbChyZXN1bHQsIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgcmVjZWl2ZSBhZGRyZXNzIChpbmRleCA+IDApJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgYWRkcmVzczogdGVzdFdhbGxldERhdGEucmVjZWl2ZUFkZHJlc3MsXG4gICAgICAgIGtleWNoYWluczogdGVzdFdhbGxldERhdGEua2V5Y2hhaW5zLFxuICAgICAgICBpbmRleDogdGVzdFdhbGxldERhdGEucmVjZWl2ZUFkZHJlc3NJbmRleCxcbiAgICAgICAgY2hhaW46IDAsXG4gICAgICB9KTtcbiAgICAgIGFzc2VydC5lcXVhbChyZXN1bHQsIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYWRkcmVzcyB3aXRoIGluZGV4IGluIGNvaW5TcGVjaWZpYycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3RXYWxsZXREYXRhLnJvb3RBZGRyZXNzLFxuICAgICAgICBrZXljaGFpbnM6IHRlc3RXYWxsZXREYXRhLmtleWNoYWlucyxcbiAgICAgICAgY29pblNwZWNpZmljOiB7IGluZGV4OiAwIH0sXG4gICAgICB9KTtcbiAgICAgIGFzc2VydC5lcXVhbChyZXN1bHQsIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYWRkcmVzcyB3aXRoIHN0cmluZyBpbmRleCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3RXYWxsZXREYXRhLnJvb3RBZGRyZXNzLFxuICAgICAgICBrZXljaGFpbnM6IHRlc3RXYWxsZXREYXRhLmtleWNoYWlucyxcbiAgICAgICAgaW5kZXg6ICcwJyxcbiAgICAgIH0pO1xuICAgICAgYXNzZXJ0LmVxdWFsKHJlc3VsdCwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3Igd3JvbmcgYWRkcmVzcyBhdCBpbmRleCAwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgYWRkcmVzczogdGVzdFdhbGxldERhdGEucmVjZWl2ZUFkZHJlc3MsIC8vIHdyb25nIGFkZHJlc3MgZm9yIGluZGV4IDBcbiAgICAgICAga2V5Y2hhaW5zOiB0ZXN0V2FsbGV0RGF0YS5rZXljaGFpbnMsXG4gICAgICAgIGluZGV4OiAwLFxuICAgICAgfSk7XG4gICAgICBhc3NlcnQuZXF1YWwocmVzdWx0LCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3Igd3JvbmcgYWRkcmVzcyBhdCByZWNlaXZlIGluZGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgYWRkcmVzczogdGVzdFdhbGxldERhdGEucm9vdEFkZHJlc3MsIC8vIHdyb25nIGFkZHJlc3MgZm9yIGluZGV4IDFcbiAgICAgICAga2V5Y2hhaW5zOiB0ZXN0V2FsbGV0RGF0YS5rZXljaGFpbnMsXG4gICAgICAgIGluZGV4OiB0ZXN0V2FsbGV0RGF0YS5yZWNlaXZlQWRkcmVzc0luZGV4LFxuICAgICAgICBjaGFpbjogMCxcbiAgICAgIH0pO1xuICAgICAgYXNzZXJ0LmVxdWFsKHJlc3VsdCwgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgaW52YWxpZCBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgIGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgICAgYWRkcmVzczogJ2ludmFsaWQtYWRkcmVzcycsXG4gICAgICAgICAga2V5Y2hhaW5zOiB0ZXN0V2FsbGV0RGF0YS5rZXljaGFpbnMsXG4gICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgIH0pLFxuICAgICAgICB7XG4gICAgICAgICAgbWVzc2FnZTogJ0ludmFsaWQgYWRkcmVzczogaW52YWxpZC1hZGRyZXNzJyxcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIG1pc3NpbmcgaW5kZXgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgICBhZGRyZXNzOiB0ZXN0V2FsbGV0RGF0YS5yb290QWRkcmVzcyxcbiAgICAgICAgICBrZXljaGFpbnM6IHRlc3RXYWxsZXREYXRhLmtleWNoYWlucyxcbiAgICAgICAgfSksXG4gICAgICAgIHtcbiAgICAgICAgICBtZXNzYWdlOiAnSW52YWxpZCBvciBtaXNzaW5nIGluZGV4IGZvciBhZGRyZXNzIHZlcmlmaWNhdGlvbicsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBtaXNzaW5nIGJpdGdvIGtleSBvbiByb290IGFkZHJlc3MgdmVyaWZpY2F0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgIGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgICAgYWRkcmVzczogdGVzdFdhbGxldERhdGEucm9vdEFkZHJlc3MsXG4gICAgICAgICAga2V5Y2hhaW5zOiB0ZXN0V2FsbGV0RGF0YS5rZXljaGFpbnMuc2xpY2UoMCwgMiksIC8vIG9ubHkgdXNlciBhbmQgYmFja3VwIGtleXNcbiAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgfSksXG4gICAgICAgIHtcbiAgICAgICAgICBtZXNzYWdlOiAnQml0R28gcHVibGljIGtleSByZXF1aXJlZCBmb3Igcm9vdCBhZGRyZXNzIHZlcmlmaWNhdGlvbicsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBtaXNzaW5nIHVzZXIga2V5IG9uIHJlY2VpdmUgYWRkcmVzcyB2ZXJpZmljYXRpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgICBhZGRyZXNzOiB0ZXN0V2FsbGV0RGF0YS5yZWNlaXZlQWRkcmVzcyxcbiAgICAgICAgICBrZXljaGFpbnM6IFtdLCAvLyBubyBrZXlzXG4gICAgICAgICAgaW5kZXg6IHRlc3RXYWxsZXREYXRhLnJlY2VpdmVBZGRyZXNzSW5kZXgsXG4gICAgICAgIH0pLFxuICAgICAgICB7XG4gICAgICAgICAgbWVzc2FnZTogJ1VzZXIgcHVibGljIGtleSByZXF1aXJlZCBmb3IgcmVjZWl2ZSBhZGRyZXNzIHZlcmlmaWNhdGlvbicsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
|