@bitgo/sdk-coin-xdc 1.6.0 → 1.7.0
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/src/lib/XDCValidatorABI.json +431 -0
- package/dist/src/lib/index.d.ts +2 -0
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +9 -2
- package/dist/src/lib/transactionBuilder.d.ts +22 -2
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
- package/dist/src/lib/transactionBuilder.js +49 -1
- package/dist/src/lib/uploadKycBuilder.d.ts +73 -0
- package/dist/src/lib/uploadKycBuilder.d.ts.map +1 -0
- package/dist/src/lib/uploadKycBuilder.js +110 -0
- package/dist/src/lib/validatorContract.d.ts +136 -0
- package/dist/src/lib/validatorContract.d.ts.map +1 -0
- package/dist/src/lib/validatorContract.js +62 -0
- package/dist/src/xdcToken.d.ts +11 -1
- package/dist/src/xdcToken.d.ts.map +1 -1
- package/dist/src/xdcToken.js +25 -1
- package/dist/test/resources.d.ts +21 -0
- package/dist/test/resources.d.ts.map +1 -1
- package/dist/test/resources.js +26 -2
- package/dist/test/unit/transactionBuilder/uploadKyc.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/uploadKyc.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/uploadKyc.js +215 -0
- package/dist/test/unit/xdcToken.js +200 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const getBuilder_1 = require("../getBuilder");
|
|
7
|
+
const should_1 = __importDefault(require("should"));
|
|
8
|
+
const sdk_core_1 = require("@bitgo/sdk-core");
|
|
9
|
+
const statics_1 = require("@bitgo/statics");
|
|
10
|
+
const lib_1 = require("../../../src/lib");
|
|
11
|
+
describe('XDC Upload KYC Builder', () => {
|
|
12
|
+
const coinConfig = statics_1.coins.get('txdc');
|
|
13
|
+
describe('UploadKycBuilder', () => {
|
|
14
|
+
it('should build uploadKYC call with valid IPFS hash', () => {
|
|
15
|
+
const builder = new lib_1.UploadKycBuilder(coinConfig);
|
|
16
|
+
const ipfsHash = 'QmRealIPFSHashExample123456789012345678901234';
|
|
17
|
+
const call = builder.ipfsHash(ipfsHash).build();
|
|
18
|
+
should_1.default.exist(call);
|
|
19
|
+
call.should.be.instanceOf(lib_1.UploadKycCall);
|
|
20
|
+
call.ipfsHash.should.equal(ipfsHash);
|
|
21
|
+
call.contractAddress.should.equal(lib_1.XDC_VALIDATOR_CONTRACT_ADDRESS_TESTNET);
|
|
22
|
+
});
|
|
23
|
+
it('should build uploadKYC call with custom contract address', () => {
|
|
24
|
+
const builder = new lib_1.UploadKycBuilder(coinConfig);
|
|
25
|
+
const ipfsHash = 'QmCustomIPFSHash123456789012345678901234567';
|
|
26
|
+
const customAddress = '0x1234567890123456789012345678901234567890';
|
|
27
|
+
const call = builder.ipfsHash(ipfsHash).contractAddress(customAddress).build();
|
|
28
|
+
should_1.default.exist(call);
|
|
29
|
+
call.contractAddress.should.equal(customAddress);
|
|
30
|
+
});
|
|
31
|
+
it('should accept IPFS v1 hash format (starting with "b")', () => {
|
|
32
|
+
const builder = new lib_1.UploadKycBuilder(coinConfig);
|
|
33
|
+
const ipfsHash = 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi';
|
|
34
|
+
const call = builder.ipfsHash(ipfsHash).build();
|
|
35
|
+
should_1.default.exist(call);
|
|
36
|
+
call.ipfsHash.should.equal(ipfsHash);
|
|
37
|
+
});
|
|
38
|
+
it('should throw error when IPFS hash is empty', () => {
|
|
39
|
+
const builder = new lib_1.UploadKycBuilder(coinConfig);
|
|
40
|
+
(() => builder.ipfsHash('')).should.throw('IPFS hash cannot be empty');
|
|
41
|
+
});
|
|
42
|
+
it('should throw error when IPFS hash format is invalid', () => {
|
|
43
|
+
const builder = new lib_1.UploadKycBuilder(coinConfig);
|
|
44
|
+
(() => builder.ipfsHash('InvalidHash123')).should.throw('Invalid IPFS hash format. Expected hash starting with "Qm" (v0) or "b" (v1)');
|
|
45
|
+
});
|
|
46
|
+
it('should throw error when contract address is empty', () => {
|
|
47
|
+
const builder = new lib_1.UploadKycBuilder(coinConfig);
|
|
48
|
+
(() => builder.contractAddress('')).should.throw('Contract address cannot be empty');
|
|
49
|
+
});
|
|
50
|
+
it('should throw error when contract address format is invalid', () => {
|
|
51
|
+
const builder = new lib_1.UploadKycBuilder(coinConfig);
|
|
52
|
+
(() => builder.contractAddress('InvalidAddress')).should.throw('Invalid contract address format');
|
|
53
|
+
});
|
|
54
|
+
it('should throw error when building without IPFS hash', () => {
|
|
55
|
+
const builder = new lib_1.UploadKycBuilder(coinConfig);
|
|
56
|
+
(() => builder.build()).should.throw('Missing IPFS hash for uploadKYC transaction');
|
|
57
|
+
});
|
|
58
|
+
it('should normalize contract address with 0x prefix', () => {
|
|
59
|
+
const builder = new lib_1.UploadKycBuilder(coinConfig);
|
|
60
|
+
const ipfsHash = 'QmTestHash123456789012345678901234567890123';
|
|
61
|
+
const addressWithoutPrefix = '1234567890123456789012345678901234567890';
|
|
62
|
+
const call = builder.ipfsHash(ipfsHash).contractAddress(addressWithoutPrefix).build();
|
|
63
|
+
call.contractAddress.should.equal('0x' + addressWithoutPrefix);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('UploadKycCall', () => {
|
|
67
|
+
it('should serialize uploadKYC call correctly', () => {
|
|
68
|
+
const ipfsHash = 'QmTestIPFSHash1234567890123456789012345678';
|
|
69
|
+
const contractAddress = lib_1.XDC_VALIDATOR_CONTRACT_ADDRESS_TESTNET;
|
|
70
|
+
const call = new lib_1.UploadKycCall(contractAddress, ipfsHash);
|
|
71
|
+
const serialized = call.serialize();
|
|
72
|
+
should_1.default.exist(serialized);
|
|
73
|
+
serialized.should.be.type('string');
|
|
74
|
+
// Should start with the method ID
|
|
75
|
+
serialized.should.startWith(lib_1.UPLOAD_KYC_METHOD_ID);
|
|
76
|
+
});
|
|
77
|
+
it('should have correct properties', () => {
|
|
78
|
+
const ipfsHash = 'QmTestIPFSHash1234567890123456789012345678';
|
|
79
|
+
const contractAddress = '0x0000000000000000000000000000000000000088';
|
|
80
|
+
const call = new lib_1.UploadKycCall(contractAddress, ipfsHash);
|
|
81
|
+
call.contractAddress.should.equal(contractAddress);
|
|
82
|
+
call.ipfsHash.should.equal(ipfsHash);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('TransactionBuilder integration', () => {
|
|
86
|
+
it('should build uploadKYC transaction with TransactionBuilder', async () => {
|
|
87
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('txdc');
|
|
88
|
+
const ipfsHash = 'QmTestIPFSHash1234567890123456789012345678';
|
|
89
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
90
|
+
txBuilder.fee({
|
|
91
|
+
fee: '10000000000',
|
|
92
|
+
gasLimit: '100000',
|
|
93
|
+
});
|
|
94
|
+
txBuilder.counter(1);
|
|
95
|
+
txBuilder.uploadKyc().ipfsHash(ipfsHash);
|
|
96
|
+
const tx = await txBuilder.build();
|
|
97
|
+
should_1.default.exist(tx);
|
|
98
|
+
const txJson = tx.toJson();
|
|
99
|
+
should_1.default.exist(txJson.to);
|
|
100
|
+
txJson.to.should.equal(lib_1.XDC_VALIDATOR_CONTRACT_ADDRESS_TESTNET);
|
|
101
|
+
txJson.value.should.equal('0');
|
|
102
|
+
should_1.default.exist(txJson.data);
|
|
103
|
+
// Data should start with uploadKYC method ID
|
|
104
|
+
txJson.data.should.startWith(lib_1.UPLOAD_KYC_METHOD_ID);
|
|
105
|
+
});
|
|
106
|
+
it('should throw error when uploadKyc() is called on non-ContractCall transaction', () => {
|
|
107
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('txdc');
|
|
108
|
+
txBuilder.type(sdk_core_1.TransactionType.Send);
|
|
109
|
+
(() => txBuilder.uploadKyc()).should.throw('uploadKYC can only be set for contract call transactions');
|
|
110
|
+
});
|
|
111
|
+
it('should build transaction with custom validator contract address', async () => {
|
|
112
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('txdc');
|
|
113
|
+
const ipfsHash = 'QmCustomIPFSHash123456789012345678901234567';
|
|
114
|
+
const customAddress = '0x1234567890123456789012345678901234567890';
|
|
115
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
116
|
+
txBuilder.fee({
|
|
117
|
+
fee: '10000000000',
|
|
118
|
+
gasLimit: '100000',
|
|
119
|
+
});
|
|
120
|
+
txBuilder.counter(1);
|
|
121
|
+
txBuilder.uploadKyc().ipfsHash(ipfsHash).contractAddress(customAddress);
|
|
122
|
+
const tx = await txBuilder.build();
|
|
123
|
+
should_1.default.exist(tx);
|
|
124
|
+
const txJson = tx.toJson();
|
|
125
|
+
should_1.default.exist(txJson.to);
|
|
126
|
+
txJson.to.should.equal(customAddress);
|
|
127
|
+
});
|
|
128
|
+
it('should build and serialize uploadKYC transaction', async () => {
|
|
129
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('txdc');
|
|
130
|
+
const ipfsHash = 'QmRealIPFSHashForSerialization1234567890123';
|
|
131
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
132
|
+
txBuilder.fee({
|
|
133
|
+
fee: '10000000000',
|
|
134
|
+
gasLimit: '100000',
|
|
135
|
+
});
|
|
136
|
+
txBuilder.counter(5);
|
|
137
|
+
txBuilder.uploadKyc().ipfsHash(ipfsHash);
|
|
138
|
+
const tx = await txBuilder.build();
|
|
139
|
+
const serialized = tx.toBroadcastFormat();
|
|
140
|
+
should_1.default.exist(serialized);
|
|
141
|
+
serialized.should.be.type('string');
|
|
142
|
+
// Should be a valid hex string
|
|
143
|
+
serialized.should.match(/^(0x)?[0-9a-f]+$/i);
|
|
144
|
+
});
|
|
145
|
+
it('should parse uploadKYC transaction from hex', async () => {
|
|
146
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('txdc');
|
|
147
|
+
const ipfsHash = 'QmParseTestHash12345678901234567890123456';
|
|
148
|
+
// First build a transaction
|
|
149
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
150
|
+
txBuilder.fee({
|
|
151
|
+
fee: '10000000000',
|
|
152
|
+
gasLimit: '100000',
|
|
153
|
+
});
|
|
154
|
+
txBuilder.counter(10);
|
|
155
|
+
txBuilder.uploadKyc().ipfsHash(ipfsHash);
|
|
156
|
+
const tx = await txBuilder.build();
|
|
157
|
+
const serialized = tx.toBroadcastFormat();
|
|
158
|
+
// Now parse it back
|
|
159
|
+
const txBuilder2 = (0, getBuilder_1.getBuilder)('txdc');
|
|
160
|
+
txBuilder2.from(serialized);
|
|
161
|
+
const parsedTx = await txBuilder2.build();
|
|
162
|
+
should_1.default.exist(parsedTx);
|
|
163
|
+
const parsedJson = parsedTx.toJson();
|
|
164
|
+
should_1.default.exist(parsedJson.to);
|
|
165
|
+
parsedJson.to.should.equal(lib_1.XDC_VALIDATOR_CONTRACT_ADDRESS_TESTNET);
|
|
166
|
+
parsedJson.nonce.should.equal(10);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
describe('Real-world scenarios', () => {
|
|
170
|
+
it('should create transaction matching sandbox code pattern', async () => {
|
|
171
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('txdc');
|
|
172
|
+
// Mock IPFS hash similar to what would be generated
|
|
173
|
+
const mockIPFSHash = 'Qm' + 'a'.repeat(44);
|
|
174
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
175
|
+
txBuilder.fee({
|
|
176
|
+
fee: '20000000000',
|
|
177
|
+
gasLimit: '200000',
|
|
178
|
+
});
|
|
179
|
+
txBuilder.counter(0);
|
|
180
|
+
txBuilder.uploadKyc().ipfsHash(mockIPFSHash);
|
|
181
|
+
const tx = await txBuilder.build();
|
|
182
|
+
const txJson = tx.toJson();
|
|
183
|
+
// Verify transaction structure matches expected format
|
|
184
|
+
should_1.default.exist(txJson.to);
|
|
185
|
+
txJson.to.should.equal(lib_1.XDC_VALIDATOR_CONTRACT_ADDRESS_TESTNET);
|
|
186
|
+
txJson.value.should.equal('0');
|
|
187
|
+
should_1.default.exist(txJson.data);
|
|
188
|
+
txJson.data.should.startWith(lib_1.UPLOAD_KYC_METHOD_ID);
|
|
189
|
+
should_1.default.exist(txJson.gasLimit);
|
|
190
|
+
should_1.default.exist(txJson.nonce);
|
|
191
|
+
});
|
|
192
|
+
it('should handle multiple IPFS hash formats', async () => {
|
|
193
|
+
const testHashes = [
|
|
194
|
+
'QmRealIPFSHashExample123456789012345678901234', // v0
|
|
195
|
+
'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi', // v1
|
|
196
|
+
'QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG', // real example
|
|
197
|
+
];
|
|
198
|
+
for (const hash of testHashes) {
|
|
199
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('txdc');
|
|
200
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
201
|
+
txBuilder.fee({
|
|
202
|
+
fee: '10000000000',
|
|
203
|
+
gasLimit: '100000',
|
|
204
|
+
});
|
|
205
|
+
txBuilder.counter(1);
|
|
206
|
+
txBuilder.uploadKyc().ipfsHash(hash);
|
|
207
|
+
const tx = await txBuilder.build();
|
|
208
|
+
should_1.default.exist(tx);
|
|
209
|
+
const txJson = tx.toJson();
|
|
210
|
+
txJson.data.should.startWith(lib_1.UPLOAD_KYC_METHOD_ID);
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkS3ljLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC91bml0L3RyYW5zYWN0aW9uQnVpbGRlci91cGxvYWRLeWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw4Q0FBMkM7QUFDM0Msb0RBQTRCO0FBQzVCLDhDQUFrRDtBQUNsRCw0Q0FBdUM7QUFDdkMsMENBSzBCO0FBRTFCLFFBQVEsQ0FBQyx3QkFBd0IsRUFBRSxHQUFHLEVBQUU7SUFDdEMsTUFBTSxVQUFVLEdBQUcsZUFBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUVyQyxRQUFRLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxFQUFFO1FBQ2hDLEVBQUUsQ0FBQyxrREFBa0QsRUFBRSxHQUFHLEVBQUU7WUFDMUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxzQkFBZ0IsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNqRCxNQUFNLFFBQVEsR0FBRywrQ0FBK0MsQ0FBQztZQUVqRSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBRWhELGdCQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ25CLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxtQkFBYSxDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3JDLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyw0Q0FBc0MsQ0FBQyxDQUFDO1FBQzVFLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDBEQUEwRCxFQUFFLEdBQUcsRUFBRTtZQUNsRSxNQUFNLE9BQU8sR0FBRyxJQUFJLHNCQUFnQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ2pELE1BQU0sUUFBUSxHQUFHLDZD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R0FBRztnQkFDakIsK0NBQStDLEVBQUUsS0FBSztnQkFDdEQsNkRBQTZELEVBQUUsS0FBSztnQkFDcEUsZ0RBQWdELEVBQUUsZUFBZTthQUNsRSxDQUFDO1lBRUYsS0FBSyxNQUFNLElBQUksSUFBSSxVQUFVLEVBQUUsQ0FBQztnQkFDOUIsTUFBTSxTQUFTLEdBQUcsSUFBQSx1QkFBVSxFQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUVyQyxTQUFTLENBQUMsSUFBSSxDQUFDLDBCQUFlLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQzdDLFNBQVMsQ0FBQyxHQUFHLENBQUM7b0JBQ1osR0FBRyxFQUFFLGFBQWE7b0JBQ2xCLFFBQVEsRUFBRSxRQUFRO2lCQUNuQixDQUFDLENBQUM7Z0JBQ0gsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDckIsU0FBUyxDQUFDLFNBQVMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFckMsTUFBTSxFQUFFLEdBQUcsTUFBTSxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ25DLGdCQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUVqQixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQzNCLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQywwQkFBb0IsQ0FBQyxDQUFDO1lBQ3JELENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBnZXRCdWlsZGVyIH0gZnJvbSAnLi4vZ2V0QnVpbGRlcic7XG5pbXBvcnQgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvblR5cGUgfSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgY29pbnMgfSBmcm9tICdAYml0Z28vc3RhdGljcyc7XG5pbXBvcnQge1xuICBVcGxvYWRLeWNCdWlsZGVyLFxuICBVcGxvYWRLeWNDYWxsLFxuICBYRENfVkFMSURBVE9SX0NPTlRSQUNUX0FERFJFU1NfVEVTVE5FVCxcbiAgVVBMT0FEX0tZQ19NRVRIT0RfSUQsXG59IGZyb20gJy4uLy4uLy4uL3NyYy9saWInO1xuXG5kZXNjcmliZSgnWERDIFVwbG9hZCBLWUMgQnVpbGRlcicsICgpID0+IHtcbiAgY29uc3QgY29pbkNvbmZpZyA9IGNvaW5zLmdldCgndHhkYycpO1xuXG4gIGRlc2NyaWJlKCdVcGxvYWRLeWNCdWlsZGVyJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgYnVpbGQgdXBsb2FkS1lDIGNhbGwgd2l0aCB2YWxpZCBJUEZTIGhhc2gnLCAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFVwbG9hZEt5Y0J1aWxkZXIoY29pbkNvbmZpZyk7XG4gICAgICBjb25zdCBpcGZzSGFzaCA9ICdRbVJlYWxJUEZTSGFzaEV4YW1wbGUxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQnO1xuXG4gICAgICBjb25zdCBjYWxsID0gYnVpbGRlci5pcGZzSGFzaChpcGZzSGFzaCkuYnVpbGQoKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KGNhbGwpO1xuICAgICAgY2FsbC5zaG91bGQuYmUuaW5zdGFuY2VPZihVcGxvYWRLeWNDYWxsKTtcbiAgICAgIGNhbGwuaXBmc0hhc2guc2hvdWxkLmVxdWFsKGlwZnNIYXNoKTtcbiAgICAgIGNhbGwuY29udHJhY3RBZGRyZXNzLnNob3VsZC5lcXVhbChYRENfVkFMSURBVE9SX0NPTlRSQUNUX0FERFJFU1NfVEVTVE5FVCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIHVwbG9hZEtZQyBjYWxsIHdpdGggY3VzdG9tIGNvbnRyYWN0IGFkZHJlc3MnLCAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFVwbG9hZEt5Y0J1aWxkZXIoY29pbkNvbmZpZyk7XG4gICAgICBjb25zdCBpcGZzSGFzaCA9ICdRbUN1c3RvbUlQRlNIYXNoMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3JztcbiAgICAgIGNvbnN0IGN1c3RvbUFkZHJlc3MgPSAnMHgxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwJztcblxuICAgICAgY29uc3QgY2FsbCA9IGJ1aWxkZXIuaXBmc0hhc2goaXBmc0hhc2gpLmNvbnRyYWN0QWRkcmVzcyhjdXN0b21BZGRyZXNzKS5idWlsZCgpO1xuXG4gICAgICBzaG91bGQuZXhpc3QoY2FsbCk7XG4gICAgICBjYWxsLmNvbnRyYWN0QWRkcmVzcy5zaG91bGQuZXF1YWwoY3VzdG9tQWRkcmVzcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGFjY2VwdCBJUEZTIHYxIGhhc2ggZm9ybWF0IChzdGFydGluZyB3aXRoIFwiYlwiKScsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVXBsb2FkS3ljQnVpbGRlcihjb2luQ29uZmlnKTtcbiAgICAgIGNvbnN0IGlwZnNIYXNoID0gJ2JhZnliZWlnZHlyenQ1c2ZwN3VkbTdodTc2dWg3eTI2bmYzZWZ1eWxxYWJmM29jbGd0cXk1NWZiemRpJztcblxuICAgICAgY29uc3QgY2FsbCA9IGJ1aWxkZXIuaXBmc0hhc2goaXBmc0hhc2gpLmJ1aWxkKCk7XG5cbiAgICAgIHNob3VsZC5leGlzdChjYWxsKTtcbiAgICAgIGNhbGwuaXBmc0hhc2guc2hvdWxkLmVxdWFsKGlwZnNIYXNoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBJUEZTIGhhc2ggaXMgZW1wdHknLCAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFVwbG9hZEt5Y0J1aWxkZXIoY29pbkNvbmZpZyk7XG5cbiAgICAgICgoKSA9PiBidWlsZGVyLmlwZnNIYXNoKCcnKSkuc2hvdWxkLnRocm93KCdJUEZTIGhhc2ggY2Fubm90IGJlIGVtcHR5Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gSVBGUyBoYXNoIGZvcm1hdCBpcyBpbnZhbGlkJywgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBVcGxvYWRLeWNCdWlsZGVyKGNvaW5Db25maWcpO1xuXG4gICAgICAoKCkgPT4gYnVpbGRlci5pcGZzSGFzaCgnSW52YWxpZEhhc2gxMjMnKSkuc2hvdWxkLnRocm93KFxuICAgICAgICAnSW52YWxpZCBJUEZTIGhhc2ggZm9ybWF0LiBFeHBlY3RlZCBoYXNoIHN0YXJ0aW5nIHdpdGggXCJRbVwiICh2MCkgb3IgXCJiXCIgKHYxKSdcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gY29udHJhY3QgYWRkcmVzcyBpcyBlbXB0eScsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVXBsb2FkS3ljQnVpbGRlcihjb2luQ29uZmlnKTtcblxuICAgICAgKCgpID0+IGJ1aWxkZXIuY29udHJhY3RBZGRyZXNzKCcnKSkuc2hvdWxkLnRocm93KCdDb250cmFjdCBhZGRyZXNzIGNhbm5vdCBiZSBlbXB0eScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIGNvbnRyYWN0IGFkZHJlc3MgZm9ybWF0IGlzIGludmFsaWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFVwbG9hZEt5Y0J1aWxkZXIoY29pbkNvbmZpZyk7XG5cbiAgICAgICgoKSA9PiBidWlsZGVyLmNvbnRyYWN0QWRkcmVzcygnSW52YWxpZEFkZHJlc3MnKSkuc2hvdWxkLnRocm93KCdJbnZhbGlkIGNvbnRyYWN0IGFkZHJlc3MgZm9ybWF0Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gYnVpbGRpbmcgd2l0aG91dCBJUEZTIGhhc2gnLCAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFVwbG9hZEt5Y0J1aWxkZXIoY29pbkNvbmZpZyk7XG5cbiAgICAgICgoKSA9PiBidWlsZGVyLmJ1aWxkKCkpLnNob3VsZC50aHJvdygnTWlzc2luZyBJUEZTIGhhc2ggZm9yIHVwbG9hZEtZQyB0cmFuc2FjdGlvbicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBub3JtYWxpemUgY29udHJhY3QgYWRkcmVzcyB3aXRoIDB4IHByZWZpeCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVXBsb2FkS3ljQnVpbGRlcihjb2luQ29uZmlnKTtcbiAgICAgIGNvbnN0IGlwZnNIYXNoID0gJ1FtVGVzdEhhc2gxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjMnO1xuICAgICAgY29uc3QgYWRkcmVzc1dpdGhvdXRQcmVmaXggPSAnMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MCc7XG5cbiAgICAgIGNvbnN0IGNhbGwgPSBidWlsZGVyLmlwZnNIYXNoKGlwZnNIYXNoKS5jb250cmFjdEFkZHJlc3MoYWRkcmVzc1dpdGhvdXRQcmVmaXgpLmJ1aWxkKCk7XG5cbiAgICAgIGNhbGwuY29udHJhY3RBZGRyZXNzLnNob3VsZC5lcXVhbCgnMHgnICsgYWRkcmVzc1dpdGhvdXRQcmVmaXgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVXBsb2FkS3ljQ2FsbCcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHNlcmlhbGl6ZSB1cGxvYWRLWUMgY2FsbCBjb3JyZWN0bHknLCAoKSA9PiB7XG4gICAgICBjb25zdCBpcGZzSGFzaCA9ICdRbVRlc3RJUEZTSGFzaDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2NzgnO1xuICAgICAgY29uc3QgY29udHJhY3RBZGRyZXNzID0gWERDX1ZBTElEQVRPUl9DT05UUkFDVF9BRERSRVNTX1RFU1RORVQ7XG5cbiAgICAgIGNvbnN0IGNhbGwgPSBuZXcgVXBsb2FkS3ljQ2FsbChjb250cmFjdEFkZHJlc3MsIGlwZnNIYXNoKTtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSBjYWxsLnNlcmlhbGl6ZSgpO1xuXG4gICAgICBzaG91bGQuZXhpc3Qoc2VyaWFsaXplZCk7XG4gICAgICBzZXJpYWxpemVkLnNob3VsZC5iZS50eXBlKCdzdHJpbmcnKTtcbiAgICAgIC8vIFNob3VsZCBzdGFydCB3aXRoIHRoZSBtZXRob2QgSURcbiAgICAgIHNlcmlhbGl6ZWQuc2hvdWxkLnN0YXJ0V2l0aChVUExPQURfS1lDX01FVEhPRF9JRCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhdmUgY29ycmVjdCBwcm9wZXJ0aWVzJywgKCkgPT4ge1xuICAgICAgY29uc3QgaXBmc0hhc2ggPSAnUW1UZXN0SVBGU0hhc2gxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4JztcbiAgICAgIGNvbnN0IGNvbnRyYWN0QWRkcmVzcyA9ICcweDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwODgnO1xuXG4gICAgICBjb25zdCBjYWxsID0gbmV3IFVwbG9hZEt5Y0NhbGwoY29udHJhY3RBZGRyZXNzLCBpcGZzSGFzaCk7XG5cbiAgICAgIGNhbGwuY29udHJhY3RBZGRyZXNzLnNob3VsZC5lcXVhbChjb250cmFjdEFkZHJlc3MpO1xuICAgICAgY2FsbC5pcGZzSGFzaC5zaG91bGQuZXF1YWwoaXBmc0hhc2gpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVHJhbnNhY3Rpb25CdWlsZGVyIGludGVncmF0aW9uJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgYnVpbGQgdXBsb2FkS1lDIHRyYW5zYWN0aW9uIHdpdGggVHJhbnNhY3Rpb25CdWlsZGVyJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcigndHhkYycpO1xuICAgICAgY29uc3QgaXBmc0hhc2ggPSAnUW1UZXN0SVBGU0hhc2gxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4JztcblxuICAgICAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCk7XG4gICAgICB0eEJ1aWxkZXIuZmVlKHtcbiAgICAgICAgZmVlOiAnMTAwMDAwMDAwMDAnLFxuICAgICAgICBnYXNMaW1pdDogJzEwMDAwMCcsXG4gICAgICB9KTtcbiAgICAgIHR4QnVpbGRlci5jb3VudGVyKDEpO1xuICAgICAgdHhCdWlsZGVyLnVwbG9hZEt5YygpLmlwZnNIYXNoKGlwZnNIYXNoKTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KHR4KTtcbiAgICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuICAgICAgc2hvdWxkLmV4aXN0KHR4SnNvbi50byk7XG4gICAgICB0eEpzb24udG8hLnNob3VsZC5lcXVhbChYRENfVkFMSURBVE9SX0NPTlRSQUNUX0FERFJFU1NfVEVTVE5FVCk7XG4gICAgICB0eEpzb24udmFsdWUuc2hvdWxkLmVxdWFsKCcwJyk7XG4gICAgICBzaG91bGQuZXhpc3QodHhKc29uLmRhdGEpO1xuICAgICAgLy8gRGF0YSBzaG91bGQgc3RhcnQgd2l0aCB1cGxvYWRLWUMgbWV0aG9kIElEXG4gICAgICB0eEpzb24uZGF0YS5zaG91bGQuc3RhcnRXaXRoKFVQTE9BRF9LWUNfTUVUSE9EX0lEKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiB1cGxvYWRLeWMoKSBpcyBjYWxsZWQgb24gbm9uLUNvbnRyYWN0Q2FsbCB0cmFuc2FjdGlvbicsICgpID0+IHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ3R4ZGMnKTtcblxuICAgICAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICAoKCkgPT4gdHhCdWlsZGVyLnVwbG9hZEt5YygpKS5zaG91bGQudGhyb3coJ3VwbG9hZEtZQyBjYW4gb25seSBiZSBzZXQgZm9yIGNvbnRyYWN0IGNhbGwgdHJhbnNhY3Rpb25zJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIHRyYW5zYWN0aW9uIHdpdGggY3VzdG9tIHZhbGlkYXRvciBjb250cmFjdCBhZGRyZXNzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcigndHhkYycpO1xuICAgICAgY29uc3QgaXBmc0hhc2ggPSAnUW1DdXN0b21JUEZTSGFzaDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nyc7XG4gICAgICBjb25zdCBjdXN0b21BZGRyZXNzID0gJzB4MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MCc7XG5cbiAgICAgIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGwpO1xuICAgICAgdHhCdWlsZGVyLmZlZSh7XG4gICAgICAgIGZlZTogJzEwMDAwMDAwMDAwJyxcbiAgICAgICAgZ2FzTGltaXQ6ICcxMDAwMDAnLFxuICAgICAgfSk7XG4gICAgICB0eEJ1aWxkZXIuY291bnRlcigxKTtcbiAgICAgIHR4QnVpbGRlci51cGxvYWRLeWMoKS5pcGZzSGFzaChpcGZzSGFzaCkuY29udHJhY3RBZGRyZXNzKGN1c3RvbUFkZHJlc3MpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuXG4gICAgICBzaG91bGQuZXhpc3QodHgpO1xuICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICBzaG91bGQuZXhpc3QodHhKc29uLnRvKTtcbiAgICAgIHR4SnNvbi50byEuc2hvdWxkLmVxdWFsKGN1c3RvbUFkZHJlc3MpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhbmQgc2VyaWFsaXplIHVwbG9hZEtZQyB0cmFuc2FjdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ3R4ZGMnKTtcbiAgICAgIGNvbnN0IGlwZnNIYXNoID0gJ1FtUmVhbElQRlNIYXNoRm9yU2VyaWFsaXphdGlvbjEyMzQ1Njc4OTAxMjMnO1xuXG4gICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgICAgIHR4QnVpbGRlci5mZWUoe1xuICAgICAgICBmZWU6ICcxMDAwMDAwMDAwMCcsXG4gICAgICAgIGdhc0xpbWl0OiAnMTAwMDAwJyxcbiAgICAgIH0pO1xuICAgICAgdHhCdWlsZGVyLmNvdW50ZXIoNSk7XG4gICAgICB0eEJ1aWxkZXIudXBsb2FkS3ljKCkuaXBmc0hhc2goaXBmc0hhc2gpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3Qgc2VyaWFsaXplZCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIHNob3VsZC5leGlzdChzZXJpYWxpemVkKTtcbiAgICAgIHNlcmlhbGl6ZWQuc2hvdWxkLmJlLnR5cGUoJ3N0cmluZycpO1xuICAgICAgLy8gU2hvdWxkIGJlIGEgdmFsaWQgaGV4IHN0cmluZ1xuICAgICAgc2VyaWFsaXplZC5zaG91bGQubWF0Y2goL14oMHgpP1swLTlhLWZdKyQvaSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhcnNlIHVwbG9hZEtZQyB0cmFuc2FjdGlvbiBmcm9tIGhleCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ3R4ZGMnKTtcbiAgICAgIGNvbnN0IGlwZnNIYXNoID0gJ1FtUGFyc2VUZXN0SGFzaDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2JztcblxuICAgICAgLy8gRmlyc3QgYnVpbGQgYSB0cmFuc2FjdGlvblxuICAgICAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCk7XG4gICAgICB0eEJ1aWxkZXIuZmVlKHtcbiAgICAgICAgZmVlOiAnMTAwMDAwMDAwMDAnLFxuICAgICAgICBnYXNMaW1pdDogJzEwMDAwMCcsXG4gICAgICB9KTtcbiAgICAgIHR4QnVpbGRlci5jb3VudGVyKDEwKTtcbiAgICAgIHR4QnVpbGRlci51cGxvYWRLeWMoKS5pcGZzSGFzaChpcGZzSGFzaCk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCBzZXJpYWxpemVkID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgLy8gTm93IHBhcnNlIGl0IGJhY2tcbiAgICAgIGNvbnN0IHR4QnVpbGRlcjIgPSBnZXRCdWlsZGVyKCd0eGRjJyk7XG4gICAgICB0eEJ1aWxkZXIyLmZyb20oc2VyaWFsaXplZCk7XG4gICAgICBjb25zdCBwYXJzZWRUeCA9IGF3YWl0IHR4QnVpbGRlcjIuYnVpbGQoKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KHBhcnNlZFR4KTtcbiAgICAgIGNvbnN0IHBhcnNlZEpzb24gPSBwYXJzZWRUeC50b0pzb24oKTtcbiAgICAgIHNob3VsZC5leGlzdChwYXJzZWRKc29uLnRvKTtcbiAgICAgIHBhcnNlZEpzb24udG8hLnNob3VsZC5lcXVhbChYRENfVkFMSURBVE9SX0NPTlRSQUNUX0FERFJFU1NfVEVTVE5FVCk7XG4gICAgICBwYXJzZWRKc29uLm5vbmNlLnNob3VsZC5lcXVhbCgxMCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSZWFsLXdvcmxkIHNjZW5hcmlvcycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSB0cmFuc2FjdGlvbiBtYXRjaGluZyBzYW5kYm94IGNvZGUgcGF0dGVybicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ3R4ZGMnKTtcbiAgICAgIC8vIE1vY2sgSVBGUyBoYXNoIHNpbWlsYXIgdG8gd2hhdCB3b3VsZCBiZSBnZW5lcmF0ZWRcbiAgICAgIGNvbnN0IG1vY2tJUEZTSGFzaCA9ICdRbScgKyAnYScucmVwZWF0KDQ0KTtcblxuICAgICAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCk7XG4gICAgICB0eEJ1aWxkZXIuZmVlKHtcbiAgICAgICAgZmVlOiAnMjAwMDAwMDAwMDAnLFxuICAgICAgICBnYXNMaW1pdDogJzIwMDAwMCcsXG4gICAgICB9KTtcbiAgICAgIHR4QnVpbGRlci5jb3VudGVyKDApO1xuICAgICAgdHhCdWlsZGVyLnVwbG9hZEt5YygpLmlwZnNIYXNoKG1vY2tJUEZTSGFzaCk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcblxuICAgICAgLy8gVmVyaWZ5IHRyYW5zYWN0aW9uIHN0cnVjdHVyZSBtYXRjaGVzIGV4cGVjdGVkIGZvcm1hdFxuICAgICAgc2hvdWxkLmV4aXN0KHR4SnNvbi50byk7XG4gICAgICB0eEpzb24udG8hLnNob3VsZC5lcXVhbChYRENfVkFMSURBVE9SX0NPTlRSQUNUX0FERFJFU1NfVEVTVE5FVCk7XG4gICAgICB0eEpzb24udmFsdWUuc2hvdWxkLmVxdWFsKCcwJyk7XG4gICAgICBzaG91bGQuZXhpc3QodHhKc29uLmRhdGEpO1xuICAgICAgdHhKc29uLmRhdGEuc2hvdWxkLnN0YXJ0V2l0aChVUExPQURfS1lDX01FVEhPRF9JRCk7XG4gICAgICBzaG91bGQuZXhpc3QodHhKc29uLmdhc0xpbWl0KTtcbiAgICAgIHNob3VsZC5leGlzdCh0eEpzb24ubm9uY2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgbXVsdGlwbGUgSVBGUyBoYXNoIGZvcm1hdHMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0SGFzaGVzID0gW1xuICAgICAgICAnUW1SZWFsSVBGU0hhc2hFeGFtcGxlMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0JywgLy8gdjBcbiAgICAgICAgJ2JhZnliZWlnZHlyenQ1c2ZwN3VkbTdodTc2dWg3eTI2bmYzZWZ1eWxxYWJmM29jbGd0cXk1NWZiemRpJywgLy8gdjFcbiAgICAgICAgJ1FtWXdBUEp6djVDWnNuQTYyNXMzWGYybmVtdFlnUHBIZFdFejc5b2pXblBiZEcnLCAvLyByZWFsIGV4YW1wbGVcbiAgICAgIF07XG5cbiAgICAgIGZvciAoY29uc3QgaGFzaCBvZiB0ZXN0SGFzaGVzKSB7XG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ3R4ZGMnKTtcblxuICAgICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgICAgICAgdHhCdWlsZGVyLmZlZSh7XG4gICAgICAgICAgZmVlOiAnMTAwMDAwMDAwMDAnLFxuICAgICAgICAgIGdhc0xpbWl0OiAnMTAwMDAwJyxcbiAgICAgICAgfSk7XG4gICAgICAgIHR4QnVpbGRlci5jb3VudGVyKDEpO1xuICAgICAgICB0eEJ1aWxkZXIudXBsb2FkS3ljKCkuaXBmc0hhc2goaGFzaCk7XG5cbiAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgc2hvdWxkLmV4aXN0KHR4KTtcblxuICAgICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgICAgdHhKc29uLmRhdGEuc2hvdWxkLnN0YXJ0V2l0aChVUExPQURfS1lDX01FVEhPRF9JRCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
|
|
@@ -4,6 +4,7 @@ require("should");
|
|
|
4
4
|
const sdk_test_1 = require("@bitgo/sdk-test");
|
|
5
5
|
const sdk_api_1 = require("@bitgo/sdk-api");
|
|
6
6
|
const src_1 = require("../../src");
|
|
7
|
+
const resources_1 = require("../resources");
|
|
7
8
|
describe('XDC Token:', function () {
|
|
8
9
|
let bitgo;
|
|
9
10
|
let xdcTokenCoin;
|
|
@@ -25,5 +26,203 @@ describe('XDC Token:', function () {
|
|
|
25
26
|
xdcTokenCoin.network.should.equal('Mainnet');
|
|
26
27
|
xdcTokenCoin.decimalPlaces.should.equal(6);
|
|
27
28
|
});
|
|
29
|
+
describe('Token Registration and TransactionBuilder', function () {
|
|
30
|
+
const mainnetTokens = ['xdc:usdc', 'xdc:lbt', 'xdc:gama', 'xdc:srx', 'xdc:weth'];
|
|
31
|
+
const testnetTokens = ['txdc:tmt'];
|
|
32
|
+
describe('Mainnet tokens', function () {
|
|
33
|
+
mainnetTokens.forEach((tokenName) => {
|
|
34
|
+
it(`${tokenName} should be registered as XdcToken`, function () {
|
|
35
|
+
const token = bitgo.coin(tokenName);
|
|
36
|
+
token.should.be.instanceOf(src_1.XdcToken);
|
|
37
|
+
});
|
|
38
|
+
it(`${tokenName} should create TransactionBuilder without error`, function () {
|
|
39
|
+
const token = bitgo.coin(tokenName);
|
|
40
|
+
// @ts-expect-error - accessing protected method for testing
|
|
41
|
+
(() => token.getTransactionBuilder()).should.not.throw();
|
|
42
|
+
});
|
|
43
|
+
it(`${tokenName} should use XDC-specific TransactionBuilder`, function () {
|
|
44
|
+
const token = bitgo.coin(tokenName);
|
|
45
|
+
// @ts-expect-error - accessing protected method for testing
|
|
46
|
+
const builder = token.getTransactionBuilder();
|
|
47
|
+
builder.should.have.property('_common');
|
|
48
|
+
// Verify it's using XDC's getCommon, not EVM's
|
|
49
|
+
// XDC's TransactionBuilder should create successfully without SHARED_EVM_SDK feature
|
|
50
|
+
builder.constructor.name.should.equal('TransactionBuilder');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe('Testnet tokens', function () {
|
|
55
|
+
testnetTokens.forEach((tokenName) => {
|
|
56
|
+
it(`${tokenName} should be registered as XdcToken`, function () {
|
|
57
|
+
const token = bitgo.coin(tokenName);
|
|
58
|
+
token.should.be.instanceOf(src_1.XdcToken);
|
|
59
|
+
});
|
|
60
|
+
it(`${tokenName} should create TransactionBuilder without error`, function () {
|
|
61
|
+
const token = bitgo.coin(tokenName);
|
|
62
|
+
// @ts-expect-error - accessing protected method for testing
|
|
63
|
+
(() => token.getTransactionBuilder()).should.not.throw();
|
|
64
|
+
});
|
|
65
|
+
it(`${tokenName} should use XDC-specific TransactionBuilder`, function () {
|
|
66
|
+
const token = bitgo.coin(tokenName);
|
|
67
|
+
// @ts-expect-error - accessing protected method for testing
|
|
68
|
+
const builder = token.getTransactionBuilder();
|
|
69
|
+
builder.should.have.property('_common');
|
|
70
|
+
builder.constructor.name.should.equal('TransactionBuilder');
|
|
71
|
+
});
|
|
72
|
+
it(`${tokenName} should have correct base chain`, function () {
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
74
|
+
const token = bitgo.coin(tokenName);
|
|
75
|
+
token.getBaseChain().should.equal('txdc');
|
|
76
|
+
});
|
|
77
|
+
it(`${tokenName} should not throw "Cannot use common sdk module" error`, function () {
|
|
78
|
+
const token = bitgo.coin(tokenName);
|
|
79
|
+
let errorThrown = false;
|
|
80
|
+
let errorMessage = '';
|
|
81
|
+
try {
|
|
82
|
+
// @ts-expect-error - accessing protected method for testing
|
|
83
|
+
const builder = token.getTransactionBuilder();
|
|
84
|
+
// Try to use the builder to ensure it's fully functional
|
|
85
|
+
// @ts-expect-error - type expects TransactionType enum
|
|
86
|
+
builder.type('Send');
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
errorThrown = true;
|
|
90
|
+
errorMessage = e.message;
|
|
91
|
+
}
|
|
92
|
+
errorThrown.should.equal(false);
|
|
93
|
+
errorMessage.should.not.match(/Cannot use common sdk module/);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
it('should verify all XDC tokens use XdcToken class, not EthLikeErc20Token', function () {
|
|
98
|
+
const allTokens = [...mainnetTokens, ...testnetTokens];
|
|
99
|
+
allTokens.forEach((tokenName) => {
|
|
100
|
+
const token = bitgo.coin(tokenName);
|
|
101
|
+
token.should.be.instanceOf(src_1.XdcToken);
|
|
102
|
+
token.constructor.name.should.equal('XdcToken');
|
|
103
|
+
token.constructor.name.should.not.equal('EthLikeErc20Token');
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe('verifyTssTransaction', function () {
|
|
108
|
+
it('should return true for valid token transfer params', async function () {
|
|
109
|
+
const token = bitgo.coin('txdc:tmt');
|
|
110
|
+
const mockWallet = {};
|
|
111
|
+
const result = await token.verifyTssTransaction({
|
|
112
|
+
txParams: {
|
|
113
|
+
recipients: [
|
|
114
|
+
{
|
|
115
|
+
address: resources_1.mockTokenTransferData.recipientAddress,
|
|
116
|
+
amount: resources_1.mockTokenTransferData.tokenAmount,
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
txPrebuild: resources_1.mockTokenTransferData.txPrebuild,
|
|
121
|
+
wallet: mockWallet,
|
|
122
|
+
});
|
|
123
|
+
result.should.equal(true);
|
|
124
|
+
});
|
|
125
|
+
it('should return true for transferToken type without recipients', async function () {
|
|
126
|
+
const token = bitgo.coin('txdc:tmt');
|
|
127
|
+
const mockWallet = {};
|
|
128
|
+
const result = await token.verifyTssTransaction({
|
|
129
|
+
txParams: {
|
|
130
|
+
type: 'transferToken',
|
|
131
|
+
},
|
|
132
|
+
txPrebuild: resources_1.mockTokenTransferData.txPrebuild,
|
|
133
|
+
wallet: mockWallet,
|
|
134
|
+
});
|
|
135
|
+
result.should.equal(true);
|
|
136
|
+
});
|
|
137
|
+
it('should throw error when txParams.recipients is missing and no valid type', async function () {
|
|
138
|
+
const token = bitgo.coin('txdc:tmt');
|
|
139
|
+
const mockWallet = {};
|
|
140
|
+
await token
|
|
141
|
+
.verifyTssTransaction({
|
|
142
|
+
txParams: {},
|
|
143
|
+
txPrebuild: resources_1.mockTokenTransferData.txPrebuild,
|
|
144
|
+
wallet: mockWallet,
|
|
145
|
+
})
|
|
146
|
+
.should.be.rejectedWith('missing txParams');
|
|
147
|
+
});
|
|
148
|
+
it('should throw error when wallet is missing', async function () {
|
|
149
|
+
const token = bitgo.coin('txdc:tmt');
|
|
150
|
+
await token
|
|
151
|
+
.verifyTssTransaction({
|
|
152
|
+
txParams: {
|
|
153
|
+
recipients: [
|
|
154
|
+
{
|
|
155
|
+
address: resources_1.mockTokenTransferData.recipientAddress,
|
|
156
|
+
amount: resources_1.mockTokenTransferData.tokenAmount,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
txPrebuild: resources_1.mockTokenTransferData.txPrebuild,
|
|
161
|
+
wallet: undefined,
|
|
162
|
+
})
|
|
163
|
+
.should.be.rejectedWith('missing params');
|
|
164
|
+
});
|
|
165
|
+
it('should throw error when txPrebuild is missing', async function () {
|
|
166
|
+
const token = bitgo.coin('txdc:tmt');
|
|
167
|
+
const mockWallet = {};
|
|
168
|
+
await token
|
|
169
|
+
.verifyTssTransaction({
|
|
170
|
+
txParams: {
|
|
171
|
+
recipients: [
|
|
172
|
+
{
|
|
173
|
+
address: resources_1.mockTokenTransferData.recipientAddress,
|
|
174
|
+
amount: resources_1.mockTokenTransferData.tokenAmount,
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
txPrebuild: undefined,
|
|
179
|
+
wallet: mockWallet,
|
|
180
|
+
})
|
|
181
|
+
.should.be.rejectedWith('missing params');
|
|
182
|
+
});
|
|
183
|
+
it('should throw error for batch + hop transaction', async function () {
|
|
184
|
+
const token = bitgo.coin('txdc:tmt');
|
|
185
|
+
const mockWallet = {};
|
|
186
|
+
await token
|
|
187
|
+
.verifyTssTransaction({
|
|
188
|
+
txParams: {
|
|
189
|
+
hop: true,
|
|
190
|
+
recipients: [
|
|
191
|
+
{ address: '0x1111111111111111111111111111111111111111', amount: '1000' },
|
|
192
|
+
{ address: '0x2222222222222222222222222222222222222222', amount: '2000' },
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
txPrebuild: resources_1.mockTokenTransferData.txPrebuild,
|
|
196
|
+
wallet: mockWallet,
|
|
197
|
+
})
|
|
198
|
+
.should.be.rejectedWith('tx cannot be both a batch and hop transaction');
|
|
199
|
+
});
|
|
200
|
+
it('should not throw EIP155 error when verifying token transaction', async function () {
|
|
201
|
+
// This test ensures that verifyTssTransaction does NOT parse the txHex
|
|
202
|
+
// which would fail with "Incompatible EIP155-based V" error
|
|
203
|
+
const token = bitgo.coin('txdc:tmt');
|
|
204
|
+
const mockWallet = {};
|
|
205
|
+
// Use the signableHex (with v=51) which would fail if parsed
|
|
206
|
+
const txPrebuildWithSignableHex = {
|
|
207
|
+
...resources_1.mockTokenTransferData.txPrebuild,
|
|
208
|
+
txHex: resources_1.mockTokenTransferData.signableHex,
|
|
209
|
+
};
|
|
210
|
+
// This should NOT throw EIP155 error because verifyTssTransaction
|
|
211
|
+
// does not parse the transaction
|
|
212
|
+
const result = await token.verifyTssTransaction({
|
|
213
|
+
txParams: {
|
|
214
|
+
recipients: [
|
|
215
|
+
{
|
|
216
|
+
address: resources_1.mockTokenTransferData.recipientAddress,
|
|
217
|
+
amount: resources_1.mockTokenTransferData.tokenAmount,
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
txPrebuild: txPrebuildWithSignableHex,
|
|
222
|
+
wallet: mockWallet,
|
|
223
|
+
});
|
|
224
|
+
result.should.equal(true);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
28
227
|
});
|
|
29
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieGRjVG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L3VuaXQveGRjVG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxrQkFBZ0I7QUFDaEIsOENBQTBEO0FBQzFELDRDQUEwQztBQUUxQyxtQ0FBcUM7QUFFckMsUUFBUSxDQUFDLFlBQVksRUFBRTtJQUNyQixJQUFJLEtBQW1CLENBQUM7SUFDeEIsSUFBSSxZQUFZLENBQUM7SUFDakIsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDO0lBRTdCLE1BQU0sQ0FBQztRQUNMLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDdEQsSUFBQSxjQUFRLEVBQUMsS0FBSyxDQUFDLENBQUM7UUFDaEIsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0IsWUFBWSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdkMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMseUJBQXlCLEVBQUU7UUFDNUIsWUFBWSxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDakQsWUFBWSxDQUFDLFlBQVksRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDaEQsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDckQsWUFBWSxDQUFDLGFBQWEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDL0MsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzFDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUMzQyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdEMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzdDLFlBQVksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3QyxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICdzaG91bGQnO1xuaW1wb3J0IHsgVGVzdEJpdEdvLCBUZXN0Qml0R29BUEkgfSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuaW1wb3J0IHsgQml0R29BUEkgfSBmcm9tICdAYml0Z28vc2RrLWFwaSc7XG5cbmltcG9ydCB7IHJlZ2lzdGVyIH0gZnJvbSAnLi4vLi4vc3JjJztcblxuZGVzY3JpYmUoJ1hEQyBUb2tlbjonLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgeGRjVG9rZW5Db2luO1xuICBjb25zdCB0b2tlbk5hbWUgPSAneGRjOnVzZGMnO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAncHJvZCcgfSk7XG4gICAgcmVnaXN0ZXIoYml0Z28pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIHhkY1Rva2VuQ29pbiA9IGJpdGdvLmNvaW4odG9rZW5OYW1lKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gY29uc3RhbnRzJywgZnVuY3Rpb24gKCkge1xuICAgIHhkY1Rva2VuQ29pbi5nZXRDaGFpbigpLnNob3VsZC5lcXVhbCgneGRjOnVzZGMnKTtcbiAgICB4ZGNUb2tlbkNvaW4uZ2V0QmFzZUNoYWluKCkuc2hvdWxkLmVxdWFsKCd4ZGMnKTtcbiAgICB4ZGNUb2tlbkNvaW4uZ2V0RnVsbE5hbWUoKS5zaG91bGQuZXF1YWwoJ1hEQyBUb2tlbicpO1xuICAgIHhkY1Rva2VuQ29pbi5nZXRCYXNlRmFjdG9yKCkuc2hvdWxkLmVxdWFsKDFlNik7XG4gICAgeGRjVG9rZW5Db2luLnR5cGUuc2hvdWxkLmVxdWFsKHRva2VuTmFtZSk7XG4gICAgeGRjVG9rZW5Db2luLm5hbWUuc2hvdWxkLmVxdWFsKCdVU0QgQ29pbicpO1xuICAgIHhkY1Rva2VuQ29pbi5jb2luLnNob3VsZC5lcXVhbCgneGRjJyk7XG4gICAgeGRjVG9rZW5Db2luLm5ldHdvcmsuc2hvdWxkLmVxdWFsKCdNYWlubmV0Jyk7XG4gICAgeGRjVG9rZW5Db2luLmRlY2ltYWxQbGFjZXMuc2hvdWxkLmVxdWFsKDYpO1xuICB9KTtcbn0pO1xuIl19
|
|
228
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieGRjVG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L3VuaXQveGRjVG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxrQkFBZ0I7QUFDaEIsOENBQTBEO0FBQzFELDRDQUEwQztBQUcxQyxtQ0FBK0M7QUFDL0MsNENBQXFEO0FBRXJELFFBQVEsQ0FBQyxZQUFZLEVBQUU7SUFDckIsSUFBSSxLQUFtQixDQUFDO0lBQ3hCLElBQUksWUFBWSxDQUFDO0lBQ2pCLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQztJQUU3QixNQUFNLENBQUM7UUFDTCxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQVEsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELElBQUEsY0FBUSxFQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2hCLEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzNCLFlBQVksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3ZDLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHlCQUF5QixFQUFFO1FBQzVCLFlBQVksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2pELFlBQVksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2hELFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3JELFlBQVksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQy9DLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMxQyxZQUFZLENBQUMsSUFBSSxDQUFD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QUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgJ3Nob3VsZCc7XG5pbXBvcnQgeyBUZXN0Qml0R28sIFRlc3RCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby9zZGstdGVzdCc7XG5pbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby9zZGstYXBpJztcbmltcG9ydCB7IElXYWxsZXQgfSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuXG5pbXBvcnQgeyByZWdpc3RlciwgWGRjVG9rZW4gfSBmcm9tICcuLi8uLi9zcmMnO1xuaW1wb3J0IHsgbW9ja1Rva2VuVHJhbnNmZXJEYXRhIH0gZnJvbSAnLi4vcmVzb3VyY2VzJztcblxuZGVzY3JpYmUoJ1hEQyBUb2tlbjonLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgeGRjVG9rZW5Db2luO1xuICBjb25zdCB0b2tlbk5hbWUgPSAneGRjOnVzZGMnO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAncHJvZCcgfSk7XG4gICAgcmVnaXN0ZXIoYml0Z28pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIHhkY1Rva2VuQ29pbiA9IGJpdGdvLmNvaW4odG9rZW5OYW1lKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gY29uc3RhbnRzJywgZnVuY3Rpb24gKCkge1xuICAgIHhkY1Rva2VuQ29pbi5nZXRDaGFpbigpLnNob3VsZC5lcXVhbCgneGRjOnVzZGMnKTtcbiAgICB4ZGNUb2tlbkNvaW4uZ2V0QmFzZUNoYWluKCkuc2hvdWxkLmVxdWFsKCd4ZGMnKTtcbiAgICB4ZGNUb2tlbkNvaW4uZ2V0RnVsbE5hbWUoKS5zaG91bGQuZXF1YWwoJ1hEQyBUb2tlbicpO1xuICAgIHhkY1Rva2VuQ29pbi5nZXRCYXNlRmFjdG9yKCkuc2hvdWxkLmVxdWFsKDFlNik7XG4gICAgeGRjVG9rZW5Db2luLnR5cGUuc2hvdWxkLmVxdWFsKHRva2VuTmFtZSk7XG4gICAgeGRjVG9rZW5Db2luLm5hbWUuc2hvdWxkLmVxdWFsKCdVU0QgQ29pbicpO1xuICAgIHhkY1Rva2VuQ29pbi5jb2luLnNob3VsZC5lcXVhbCgneGRjJyk7XG4gICAgeGRjVG9rZW5Db2luLm5ldHdvcmsuc2hvdWxkLmVxdWFsKCdNYWlubmV0Jyk7XG4gICAgeGRjVG9rZW5Db2luLmRlY2ltYWxQbGFjZXMuc2hvdWxkLmVxdWFsKDYpO1xuICB9KTtcblxuICBkZXNjcmliZSgnVG9rZW4gUmVnaXN0cmF0aW9uIGFuZCBUcmFuc2FjdGlvbkJ1aWxkZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgbWFpbm5ldFRva2VucyA9IFsneGRjOnVzZGMnLCAneGRjOmxidCcsICd4ZGM6Z2FtYScsICd4ZGM6c3J4JywgJ3hkYzp3ZXRoJ107XG4gICAgY29uc3QgdGVzdG5ldFRva2VucyA9IFsndHhkYzp0bXQnXTtcblxuICAgIGRlc2NyaWJlKCdNYWlubmV0IHRva2VucycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIG1haW5uZXRUb2tlbnMuZm9yRWFjaCgodG9rZW5OYW1lKSA9PiB7XG4gICAgICAgIGl0KGAke3Rva2VuTmFtZX0gc2hvdWxkIGJlIHJlZ2lzdGVyZWQgYXMgWGRjVG9rZW5gLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY29uc3QgdG9rZW4gPSBiaXRnby5jb2luKHRva2VuTmFtZSk7XG4gICAgICAgICAgdG9rZW4uc2hvdWxkLmJlLmluc3RhbmNlT2YoWGRjVG9rZW4pO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdChgJHt0b2tlbk5hbWV9IHNob3VsZCBjcmVhdGUgVHJhbnNhY3Rpb25CdWlsZGVyIHdpdGhvdXQgZXJyb3JgLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY29uc3QgdG9rZW4gPSBiaXRnby5jb2luKHRva2VuTmFtZSkgYXMgWGRjVG9rZW47XG4gICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIGFjY2Vzc2luZyBwcm90ZWN0ZWQgbWV0aG9kIGZvciB0ZXN0aW5nXG4gICAgICAgICAgKCgpID0+IHRva2VuLmdldFRyYW5zYWN0aW9uQnVpbGRlcigpKS5zaG91bGQubm90LnRocm93KCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KGAke3Rva2VuTmFtZX0gc2hvdWxkIHVzZSBYREMtc3BlY2lmaWMgVHJhbnNhY3Rpb25CdWlsZGVyYCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IHRva2VuID0gYml0Z28uY29pbih0b2tlbk5hbWUpIGFzIFhkY1Rva2VuO1xuICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBhY2Nlc3NpbmcgcHJvdGVjdGVkIG1ldGhvZCBmb3IgdGVzdGluZ1xuICAgICAgICAgIGNvbnN0IGJ1aWxkZXIgPSB0b2tlbi5nZXRUcmFuc2FjdGlvbkJ1aWxkZXIoKTtcbiAgICAgICAgICBidWlsZGVyLnNob3VsZC5oYXZlLnByb3BlcnR5KCdfY29tbW9uJyk7XG4gICAgICAgICAgLy8gVmVyaWZ5IGl0J3MgdXNpbmcgWERDJ3MgZ2V0Q29tbW9uLCBub3QgRVZNJ3NcbiAgICAgICAgICAvLyBYREMncyBUcmFuc2FjdGlvbkJ1aWxkZXIgc2hvdWxkIGNyZWF0ZSBzdWNjZXNzZnVsbHkgd2l0aG91dCBTSEFSRURfRVZNX1NESyBmZWF0dXJlXG4gICAgICAgICAgYnVpbGRlci5jb25zdHJ1Y3Rvci5uYW1lLnNob3VsZC5lcXVhbCgnVHJhbnNhY3Rpb25CdWlsZGVyJyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnVGVzdG5ldCB0b2tlbnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0ZXN0bmV0VG9rZW5zLmZvckVhY2goKHRva2VuTmFtZSkgPT4ge1xuICAgICAgICBpdChgJHt0b2tlbk5hbWV9IHNob3VsZCBiZSByZWdpc3RlcmVkIGFzIFhkY1Rva2VuYCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IHRva2VuID0gYml0Z28uY29pbih0b2tlbk5hbWUpO1xuICAgICAgICAgIHRva2VuLnNob3VsZC5iZS5pbnN0YW5jZU9mKFhkY1Rva2VuKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoYCR7dG9rZW5OYW1lfSBzaG91bGQgY3JlYXRlIFRyYW5zYWN0aW9uQnVpbGRlciB3aXRob3V0IGVycm9yYCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IHRva2VuID0gYml0Z28uY29pbih0b2tlbk5hbWUpIGFzIFhkY1Rva2VuO1xuICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBhY2Nlc3NpbmcgcHJvdGVjdGVkIG1ldGhvZCBmb3IgdGVzdGluZ1xuICAgICAgICAgICgoKSA9PiB0b2tlbi5nZXRUcmFuc2FjdGlvbkJ1aWxkZXIoKSkuc2hvdWxkLm5vdC50aHJvdygpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdChgJHt0b2tlbk5hbWV9IHNob3VsZCB1c2UgWERDLXNwZWNpZmljIFRyYW5zYWN0aW9uQnVpbGRlcmAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCB0b2tlbiA9IGJpdGdvLmNvaW4odG9rZW5OYW1lKSBhcyBYZGNUb2tlbjtcbiAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gYWNjZXNzaW5nIHByb3RlY3RlZCBtZXRob2QgZm9yIHRlc3RpbmdcbiAgICAgICAgICBjb25zdCBidWlsZGVyID0gdG9rZW4uZ2V0VHJhbnNhY3Rpb25CdWlsZGVyKCk7XG4gICAgICAgICAgYnVpbGRlci5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnX2NvbW1vbicpO1xuICAgICAgICAgIGJ1aWxkZXIuY29uc3RydWN0b3IubmFtZS5zaG91bGQuZXF1YWwoJ1RyYW5zYWN0aW9uQnVpbGRlcicpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdChgJHt0b2tlbk5hbWV9IHNob3VsZCBoYXZlIGNvcnJlY3QgYmFzZSBjaGFpbmAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAgIGNvbnN0IHRva2VuOiBhbnkgPSBiaXRnby5jb2luKHRva2VuTmFtZSk7XG4gICAgICAgICAgdG9rZW4uZ2V0QmFzZUNoYWluKCkuc2hvdWxkLmVxdWFsKCd0eGRjJyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KGAke3Rva2VuTmFtZX0gc2hvdWxkIG5vdCB0aHJvdyBcIkNhbm5vdCB1c2UgY29tbW9uIHNkayBtb2R1bGVcIiBlcnJvcmAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCB0b2tlbiA9IGJpdGdvLmNvaW4odG9rZW5OYW1lKSBhcyBYZGNUb2tlbjtcbiAgICAgICAgICBsZXQgZXJyb3JUaHJvd24gPSBmYWxzZTtcbiAgICAgICAgICBsZXQgZXJyb3JNZXNzYWdlID0gJyc7XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIGFjY2Vzc2luZyBwcm90ZWN0ZWQgbWV0aG9kIGZvciB0ZXN0aW5nXG4gICAgICAgICAgICBjb25zdCBidWlsZGVyID0gdG9rZW4uZ2V0VHJhbnNhY3Rpb25CdWlsZGVyKCk7XG4gICAgICAgICAgICAvLyBUcnkgdG8gdXNlIHRoZSBidWlsZGVyIHRvIGVuc3VyZSBpdCdzIGZ1bGx5IGZ1bmN0aW9uYWxcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSB0eXBlIGV4cGVjdHMgVHJhbnNhY3Rpb25UeXBlIGVudW1cbiAgICAgICAgICAgIGJ1aWxkZXIudHlwZSgnU2VuZCcpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGVycm9yVGhyb3duID0gdHJ1ZTtcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IChlIGFzIEVycm9yKS5tZXNzYWdlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGVycm9yVGhyb3duLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gICAgICAgICAgZXJyb3JNZXNzYWdlLnNob3VsZC5ub3QubWF0Y2goL0Nhbm5vdCB1c2UgY29tbW9uIHNkayBtb2R1bGUvKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGFsbCBYREMgdG9rZW5zIHVzZSBYZGNUb2tlbiBjbGFzcywgbm90IEV0aExpa2VFcmMyMFRva2VuJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWxsVG9rZW5zID0gWy4uLm1haW5uZXRUb2tlbnMsIC4uLnRlc3RuZXRUb2tlbnNdO1xuXG4gICAgICBhbGxUb2tlbnMuZm9yRWFjaCgodG9rZW5OYW1lKSA9PiB7XG4gICAgICAgIGNvbnN0IHRva2VuID0gYml0Z28uY29pbih0b2tlbk5hbWUpO1xuICAgICAgICB0b2tlbi5zaG91bGQuYmUuaW5zdGFuY2VPZihYZGNUb2tlbik7XG4gICAgICAgIHRva2VuLmNvbnN0cnVjdG9yLm5hbWUuc2hvdWxkLmVxdWFsKCdYZGNUb2tlbicpO1xuICAgICAgICB0b2tlbi5jb25zdHJ1Y3Rvci5uYW1lLnNob3VsZC5ub3QuZXF1YWwoJ0V0aExpa2VFcmMyMFRva2VuJyk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3ZlcmlmeVRzc1RyYW5zYWN0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIHZhbGlkIHRva2VuIHRyYW5zZmVyIHBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHRva2VuID0gYml0Z28uY29pbigndHhkYzp0bXQnKSBhcyBYZGNUb2tlbjtcbiAgICAgIGNvbnN0IG1vY2tXYWxsZXQgPSB7fSBhcyB1bmtub3duIGFzIElXYWxsZXQ7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRva2VuLnZlcmlmeVRzc1RyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFkZHJlc3M6IG1vY2tUb2tlblRyYW5zZmVyRGF0YS5yZWNpcGllbnRBZGRyZXNzLFxuICAgICAgICAgICAgICBhbW91bnQ6IG1vY2tUb2tlblRyYW5zZmVyRGF0YS50b2tlbkFtb3VudCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgdHhQcmVidWlsZDogbW9ja1Rva2VuVHJhbnNmZXJEYXRhLnR4UHJlYnVpbGQgYXMgdW5rbm93biBhcyBQYXJhbWV0ZXJzPFxuICAgICAgICAgIHR5cGVvZiB0b2tlbi52ZXJpZnlUc3NUcmFuc2FjdGlvblxuICAgICAgICA+WzBdWyd0eFByZWJ1aWxkJ10sXG4gICAgICAgIHdhbGxldDogbW9ja1dhbGxldCxcbiAgICAgIH0pO1xuXG4gICAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgdHJhbnNmZXJUb2tlbiB0eXBlIHdpdGhvdXQgcmVjaXBpZW50cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHRva2VuID0gYml0Z28uY29pbigndHhkYzp0bXQnKSBhcyBYZGNUb2tlbjtcbiAgICAgIGNvbnN0IG1vY2tXYWxsZXQgPSB7fSBhcyB1bmtub3duIGFzIElXYWxsZXQ7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRva2VuLnZlcmlmeVRzc1RyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICB0eXBlOiAndHJhbnNmZXJUb2tlbicsXG4gICAgICAgIH0sXG4gICAgICAgIHR4UHJlYnVpbGQ6IG1vY2tUb2tlblRyYW5zZmVyRGF0YS50eFByZWJ1aWxkIGFzIHVua25vd24gYXMgUGFyYW1ldGVyczxcbiAgICAgICAgICB0eXBlb2YgdG9rZW4udmVyaWZ5VHNzVHJhbnNhY3Rpb25cbiAgICAgICAgPlswXVsndHhQcmVidWlsZCddLFxuICAgICAgICB3YWxsZXQ6IG1vY2tXYWxsZXQsXG4gICAgICB9KTtcblxuICAgICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiB0eFBhcmFtcy5yZWNpcGllbnRzIGlzIG1pc3NpbmcgYW5kIG5vIHZhbGlkIHR5cGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0b2tlbiA9IGJpdGdvLmNvaW4oJ3R4ZGM6dG10JykgYXMgWGRjVG9rZW47XG4gICAgICBjb25zdCBtb2NrV2FsbGV0ID0ge30gYXMgdW5rbm93biBhcyBJV2FsbGV0O1xuXG4gICAgICBhd2FpdCB0b2tlblxuICAgICAgICAudmVyaWZ5VHNzVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7fSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiBtb2NrVG9rZW5UcmFuc2ZlckRhdGEudHhQcmVidWlsZCBhcyB1bmtub3duIGFzIFBhcmFtZXRlcnM8XG4gICAgICAgICAgICB0eXBlb2YgdG9rZW4udmVyaWZ5VHNzVHJhbnNhY3Rpb25cbiAgICAgICAgICA+WzBdWyd0eFByZWJ1aWxkJ10sXG4gICAgICAgICAgd2FsbGV0OiBtb2NrV2FsbGV0LFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyB0eFBhcmFtcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIHdhbGxldCBpcyBtaXNzaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdG9rZW4gPSBiaXRnby5jb2luKCd0eGRjOnRtdCcpIGFzIFhkY1Rva2VuO1xuXG4gICAgICBhd2FpdCB0b2tlblxuICAgICAgICAudmVyaWZ5VHNzVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhZGRyZXNzOiBtb2NrVG9rZW5UcmFuc2ZlckRhdGEucmVjaXBpZW50QWRkcmVzcyxcbiAgICAgICAgICAgICAgICBhbW91bnQ6IG1vY2tUb2tlblRyYW5zZmVyRGF0YS50b2tlbkFtb3VudCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiBtb2NrVG9rZW5UcmFuc2ZlckRhdGEudHhQcmVidWlsZCBhcyB1bmtub3duIGFzIFBhcmFtZXRlcnM8XG4gICAgICAgICAgICB0eXBlb2YgdG9rZW4udmVyaWZ5VHNzVHJhbnNhY3Rpb25cbiAgICAgICAgICA+WzBdWyd0eFByZWJ1aWxkJ10sXG4gICAgICAgICAgd2FsbGV0OiB1bmRlZmluZWQgYXMgdW5rbm93biBhcyBJV2FsbGV0LFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyBwYXJhbXMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiB0eFByZWJ1aWxkIGlzIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0b2tlbiA9IGJpdGdvLmNvaW4oJ3R4ZGM6dG10JykgYXMgWGRjVG9rZW47XG4gICAgICBjb25zdCBtb2NrV2FsbGV0ID0ge30gYXMgdW5rbm93biBhcyBJV2FsbGV0O1xuXG4gICAgICBhd2FpdCB0b2tlblxuICAgICAgICAudmVyaWZ5VHNzVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhZGRyZXNzOiBtb2NrVG9rZW5UcmFuc2ZlckRhdGEucmVjaXBpZW50QWRkcmVzcyxcbiAgICAgICAgICAgICAgICBhbW91bnQ6IG1vY2tUb2tlblRyYW5zZmVyRGF0YS50b2tlbkFtb3VudCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB1bmRlZmluZWQgYXMgdW5rbm93biBhcyBQYXJhbWV0ZXJzPHR5cGVvZiB0b2tlbi52ZXJpZnlUc3NUcmFuc2FjdGlvbj5bMF1bJ3R4UHJlYnVpbGQnXSxcbiAgICAgICAgICB3YWxsZXQ6IG1vY2tXYWxsZXQsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIHBhcmFtcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgYmF0Y2ggKyBob3AgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0b2tlbiA9IGJpdGdvLmNvaW4oJ3R4ZGM6dG10JykgYXMgWGRjVG9rZW47XG4gICAgICBjb25zdCBtb2NrV2FsbGV0ID0ge30gYXMgdW5rbm93biBhcyBJV2FsbGV0O1xuXG4gICAgICBhd2FpdCB0b2tlblxuICAgICAgICAudmVyaWZ5VHNzVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICBob3A6IHRydWUsXG4gICAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICAgIHsgYWRkcmVzczogJzB4MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMScsIGFtb3VudDogJzEwMDAnIH0sXG4gICAgICAgICAgICAgIHsgYWRkcmVzczogJzB4MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMicsIGFtb3VudDogJzIwMDAnIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDogbW9ja1Rva2VuVHJhbnNmZXJEYXRhLnR4UHJlYnVpbGQgYXMgdW5rbm93biBhcyBQYXJhbWV0ZXJzPFxuICAgICAgICAgICAgdHlwZW9mIHRva2VuLnZlcmlmeVRzc1RyYW5zYWN0aW9uXG4gICAgICAgICAgPlswXVsndHhQcmVidWlsZCddLFxuICAgICAgICAgIHdhbGxldDogbW9ja1dhbGxldCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3R4IGNhbm5vdCBiZSBib3RoIGEgYmF0Y2ggYW5kIGhvcCB0cmFuc2FjdGlvbicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBub3QgdGhyb3cgRUlQMTU1IGVycm9yIHdoZW4gdmVyaWZ5aW5nIHRva2VuIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVGhpcyB0ZXN0IGVuc3VyZXMgdGhhdCB2ZXJpZnlUc3NUcmFuc2FjdGlvbiBkb2VzIE5PVCBwYXJzZSB0aGUgdHhIZXhcbiAgICAgIC8vIHdoaWNoIHdvdWxkIGZhaWwgd2l0aCBcIkluY29tcGF0aWJsZSBFSVAxNTUtYmFzZWQgVlwiIGVycm9yXG4gICAgICBjb25zdCB0b2tlbiA9IGJpdGdvLmNvaW4oJ3R4ZGM6dG10JykgYXMgWGRjVG9rZW47XG4gICAgICBjb25zdCBtb2NrV2FsbGV0ID0ge30gYXMgdW5rbm93biBhcyBJV2FsbGV0O1xuXG4gICAgICAvLyBVc2UgdGhlIHNpZ25hYmxlSGV4ICh3aXRoIHY9NTEpIHdoaWNoIHdvdWxkIGZhaWwgaWYgcGFyc2VkXG4gICAgICBjb25zdCB0eFByZWJ1aWxkV2l0aFNpZ25hYmxlSGV4ID0ge1xuICAgICAgICAuLi5tb2NrVG9rZW5UcmFuc2ZlckRhdGEudHhQcmVidWlsZCxcbiAgICAgICAgdHhIZXg6IG1vY2tUb2tlblRyYW5zZmVyRGF0YS5zaWduYWJsZUhleCxcbiAgICAgIH07XG5cbiAgICAgIC8vIFRoaXMgc2hvdWxkIE5PVCB0aHJvdyBFSVAxNTUgZXJyb3IgYmVjYXVzZSB2ZXJpZnlUc3NUcmFuc2FjdGlvblxuICAgICAgLy8gZG9lcyBub3QgcGFyc2UgdGhlIHRyYW5zYWN0aW9uXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0b2tlbi52ZXJpZnlUc3NUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhZGRyZXNzOiBtb2NrVG9rZW5UcmFuc2ZlckRhdGEucmVjaXBpZW50QWRkcmVzcyxcbiAgICAgICAgICAgICAgYW1vdW50OiBtb2NrVG9rZW5UcmFuc2ZlckRhdGEudG9rZW5BbW91bnQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGRXaXRoU2lnbmFibGVIZXggYXMgdW5rbm93biBhcyBQYXJhbWV0ZXJzPFxuICAgICAgICAgIHR5cGVvZiB0b2tlbi52ZXJpZnlUc3NUcmFuc2FjdGlvblxuICAgICAgICA+WzBdWyd0eFByZWJ1aWxkJ10sXG4gICAgICAgIHdhbGxldDogbW9ja1dhbGxldCxcbiAgICAgIH0pO1xuXG4gICAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|