@bitgo-beta/abstract-eth 1.0.2-beta.211 → 1.0.2-beta.2111
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/abstractEthLikeCoin.d.ts +20 -9
- package/dist/src/abstractEthLikeCoin.d.ts.map +1 -1
- package/dist/src/abstractEthLikeCoin.js +46 -15
- package/dist/src/abstractEthLikeNewCoins.d.ts +876 -0
- package/dist/src/abstractEthLikeNewCoins.d.ts.map +1 -0
- package/dist/src/abstractEthLikeNewCoins.js +2664 -0
- package/dist/src/ethLikeToken.d.ts +38 -6
- package/dist/src/ethLikeToken.d.ts.map +1 -1
- package/dist/src/ethLikeToken.js +289 -10
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -2
- package/dist/src/lib/constants.d.ts +4 -0
- package/dist/src/lib/constants.d.ts.map +1 -0
- package/dist/src/lib/constants.js +11 -0
- package/dist/src/lib/contractCall.d.ts +8 -0
- package/dist/src/lib/contractCall.d.ts.map +1 -0
- package/dist/src/lib/contractCall.js +17 -0
- package/dist/src/lib/decryptionDelegationBuilder.d.ts +90 -0
- package/dist/src/lib/decryptionDelegationBuilder.d.ts.map +1 -0
- package/dist/src/lib/decryptionDelegationBuilder.js +59 -0
- package/dist/src/lib/iface.d.ts +143 -0
- package/dist/src/lib/iface.d.ts.map +1 -0
- package/dist/src/lib/iface.js +8 -0
- package/dist/src/lib/index.d.ts +19 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +60 -0
- package/dist/src/lib/keyPair.d.ts +26 -0
- package/dist/src/lib/keyPair.d.ts.map +1 -0
- package/dist/src/lib/keyPair.js +65 -0
- package/dist/src/lib/messages/eip191/eip191Message.d.ts +12 -0
- package/dist/src/lib/messages/eip191/eip191Message.d.ts.map +1 -0
- package/dist/src/lib/messages/eip191/eip191Message.js +25 -0
- package/dist/src/lib/messages/eip191/eip191MessageBuilder.d.ts +19 -0
- package/dist/src/lib/messages/eip191/eip191MessageBuilder.d.ts.map +1 -0
- package/dist/src/lib/messages/eip191/eip191MessageBuilder.js +27 -0
- package/dist/src/lib/messages/eip191/index.d.ts +3 -0
- package/dist/src/lib/messages/eip191/index.d.ts.map +1 -0
- package/dist/src/lib/messages/eip191/index.js +19 -0
- package/dist/src/lib/messages/eip712/eip712Message.d.ts +6 -0
- package/dist/src/lib/messages/eip712/eip712Message.d.ts.map +1 -0
- package/dist/src/lib/messages/eip712/eip712Message.js +27 -0
- package/dist/src/lib/messages/eip712/eip712MessageBuilder.d.ts +7 -0
- package/dist/src/lib/messages/eip712/eip712MessageBuilder.d.ts.map +1 -0
- package/dist/src/lib/messages/eip712/eip712MessageBuilder.js +15 -0
- package/dist/src/lib/messages/eip712/index.d.ts +3 -0
- package/dist/src/lib/messages/eip712/index.d.ts.map +1 -0
- package/dist/src/lib/messages/eip712/index.js +19 -0
- package/dist/src/lib/messages/index.d.ts +4 -0
- package/dist/src/lib/messages/index.d.ts.map +1 -0
- package/dist/src/lib/messages/index.js +20 -0
- package/dist/src/lib/messages/messageBuilderFactory.d.ts +7 -0
- package/dist/src/lib/messages/messageBuilderFactory.d.ts.map +1 -0
- package/dist/src/lib/messages/messageBuilderFactory.js +23 -0
- package/dist/src/lib/transaction.d.ts +69 -0
- package/dist/src/lib/transaction.d.ts.map +1 -0
- package/dist/src/lib/transaction.js +149 -0
- package/dist/src/lib/transactionBuilder.d.ts +313 -0
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
- package/dist/src/lib/transactionBuilder.js +926 -0
- package/dist/src/lib/transferBuilder.d.ts +76 -0
- package/dist/src/lib/transferBuilder.d.ts.map +1 -0
- package/dist/src/lib/transferBuilder.js +307 -0
- package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts +54 -0
- package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.js +120 -0
- package/dist/src/lib/transferBuilders/index.d.ts +5 -0
- package/dist/src/lib/transferBuilders/index.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/index.js +21 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts +17 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC1155.js +96 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts +21 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC721.js +91 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC7984.d.ts +35 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC7984.d.ts.map +1 -0
- package/dist/src/lib/transferBuilders/transferBuilderERC7984.js +113 -0
- package/dist/src/lib/types.d.ts +40 -0
- package/dist/src/lib/types.d.ts.map +1 -0
- package/dist/src/lib/types.js +140 -0
- package/dist/src/lib/utils.d.ts +365 -0
- package/dist/src/lib/utils.d.ts.map +1 -0
- package/dist/src/lib/utils.js +969 -0
- package/dist/src/lib/walletUtil.d.ts +46 -0
- package/dist/src/lib/walletUtil.d.ts.map +1 -0
- package/dist/src/lib/walletUtil.js +53 -0
- package/dist/src/lib/zamaUtils.d.ts +107 -0
- package/dist/src/lib/zamaUtils.d.ts.map +1 -0
- package/dist/src/lib/zamaUtils.js +220 -0
- package/dist/src/types.d.ts +9 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +3 -0
- package/dist/test/index.d.ts +2 -0
- package/dist/test/index.d.ts.map +1 -0
- package/dist/test/index.js +18 -0
- package/dist/test/unit/coin.d.ts +8 -0
- package/dist/test/unit/coin.d.ts.map +1 -0
- package/dist/test/unit/coin.js +577 -0
- package/dist/test/unit/decryptionDelegationBuilder.d.ts +2 -0
- package/dist/test/unit/decryptionDelegationBuilder.d.ts.map +1 -0
- package/dist/test/unit/decryptionDelegationBuilder.js +265 -0
- package/dist/test/unit/index.d.ts +8 -0
- package/dist/test/unit/index.d.ts.map +1 -0
- package/dist/test/unit/index.js +24 -0
- package/dist/test/unit/messages/abstractEthMessageBuilderTests.d.ts +3 -0
- package/dist/test/unit/messages/abstractEthMessageBuilderTests.d.ts.map +1 -0
- package/dist/test/unit/messages/abstractEthMessageBuilderTests.js +110 -0
- package/dist/test/unit/messages/abstractEthMessageTestTypes.d.ts +43 -0
- package/dist/test/unit/messages/abstractEthMessageTestTypes.d.ts.map +1 -0
- package/dist/test/unit/messages/abstractEthMessageTestTypes.js +3 -0
- package/dist/test/unit/messages/abstractEthMessagesTests.d.ts +3 -0
- package/dist/test/unit/messages/abstractEthMessagesTests.d.ts.map +1 -0
- package/dist/test/unit/messages/abstractEthMessagesTests.js +129 -0
- package/dist/test/unit/messages/eip191/eip191Message.d.ts +2 -0
- package/dist/test/unit/messages/eip191/eip191Message.d.ts.map +1 -0
- package/dist/test/unit/messages/eip191/eip191Message.js +15 -0
- package/dist/test/unit/messages/eip191/eip191MessageBuilder.d.ts +2 -0
- package/dist/test/unit/messages/eip191/eip191MessageBuilder.d.ts.map +1 -0
- package/dist/test/unit/messages/eip191/eip191MessageBuilder.js +16 -0
- package/dist/test/unit/messages/eip191/fixtures.d.ts +109 -0
- package/dist/test/unit/messages/eip191/fixtures.d.ts.map +1 -0
- package/dist/test/unit/messages/eip191/fixtures.js +63 -0
- package/dist/test/unit/messages/eip712/eip712Message.d.ts +2 -0
- package/dist/test/unit/messages/eip712/eip712Message.d.ts.map +1 -0
- package/dist/test/unit/messages/eip712/eip712Message.js +15 -0
- package/dist/test/unit/messages/eip712/eip712MessageBuilder.d.ts +2 -0
- package/dist/test/unit/messages/eip712/eip712MessageBuilder.d.ts.map +1 -0
- package/dist/test/unit/messages/eip712/eip712MessageBuilder.js +16 -0
- package/dist/test/unit/messages/eip712/fixtures.d.ts +76 -0
- package/dist/test/unit/messages/eip712/fixtures.d.ts.map +1 -0
- package/dist/test/unit/messages/eip712/fixtures.js +120 -0
- package/dist/test/unit/messages/index.d.ts +4 -0
- package/dist/test/unit/messages/index.d.ts.map +1 -0
- package/dist/test/unit/messages/index.js +20 -0
- package/dist/test/unit/messages/messageBuilderFactory.d.ts +2 -0
- package/dist/test/unit/messages/messageBuilderFactory.d.ts.map +1 -0
- package/dist/test/unit/messages/messageBuilderFactory.js +52 -0
- package/dist/test/unit/token.d.ts +2 -0
- package/dist/test/unit/token.d.ts.map +1 -0
- package/dist/test/unit/token.js +37 -0
- package/dist/test/unit/transaction.d.ts +3 -0
- package/dist/test/unit/transaction.d.ts.map +1 -0
- package/dist/test/unit/transaction.js +73 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.d.ts +8 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.js +95 -0
- package/dist/test/unit/transactionBuilder/decryptionDelegation.d.ts +3 -0
- package/dist/test/unit/transactionBuilder/decryptionDelegation.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/decryptionDelegation.js +161 -0
- package/dist/test/unit/transactionBuilder/flushERC7984.d.ts +3 -0
- package/dist/test/unit/transactionBuilder/flushERC7984.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/flushERC7984.js +292 -0
- package/dist/test/unit/transactionBuilder/flushNft.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/flushNft.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/flushNft.js +381 -0
- package/dist/test/unit/transactionBuilder/index.d.ts +7 -0
- package/dist/test/unit/transactionBuilder/index.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/index.js +23 -0
- package/dist/test/unit/transactionBuilder/send.d.ts +3 -0
- package/dist/test/unit/transactionBuilder/send.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/send.js +197 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.d.ts +11 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.js +137 -0
- package/dist/test/unit/transferBuilder.d.ts +2 -0
- package/dist/test/unit/transferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transferBuilder.js +76 -0
- package/dist/test/unit/utils.d.ts +2 -0
- package/dist/test/unit/utils.d.ts.map +1 -0
- package/dist/test/unit/utils.js +214 -0
- package/dist/test/unit/zamaUtils.d.ts +2 -0
- package/dist/test/unit/zamaUtils.d.ts.map +1 -0
- package/dist/test/unit/zamaUtils.js +352 -0
- package/dist/tsconfig.tsbuildinfo +1 -8286
- package/package.json +34 -10
- package/.eslintignore +0 -5
- package/CHANGELOG.md +0 -178
|
@@ -0,0 +1,352 @@
|
|
|
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 should_1 = __importDefault(require("should"));
|
|
7
|
+
const ethereumjs_abi_1 = __importDefault(require("ethereumjs-abi"));
|
|
8
|
+
const zamaUtils_1 = require("../../src/lib/zamaUtils");
|
|
9
|
+
const walletUtil_1 = require("../../src/lib/walletUtil");
|
|
10
|
+
describe('Zama Utils', () => {
|
|
11
|
+
const ACL_ADDRESS = '0xf0Ffdc93b7E186bC2f8CB3dAA75D86d1930A433D';
|
|
12
|
+
const DELEGATE_ADDRESS = '0x1111111111111111111111111111111111111111';
|
|
13
|
+
const TOKEN_ADDRESS = '0x94167129172A35ab093B44b8b96213DDbc3cD387';
|
|
14
|
+
const TOKEN_ADDRESS_2 = '0x4E7B06D78965594eB5EF5414c357ca21E1554491';
|
|
15
|
+
const TOKEN_ADDRESS_3 = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
|
|
16
|
+
const FORWARDER_ADDRESS = '0xDeADbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF';
|
|
17
|
+
const EXPIRY = Math.floor(Date.now() / 1000) + 365 * 86400;
|
|
18
|
+
// Helper: decode a delegateForUserDecryption call
|
|
19
|
+
function decodeDelegationCall(calldata) {
|
|
20
|
+
const payload = Buffer.from(calldata.slice(10), 'hex');
|
|
21
|
+
const decoded = ethereumjs_abi_1.default.rawDecode(['address', 'address', 'uint64'], payload);
|
|
22
|
+
return [decoded[0].toString('hex'), decoded[1].toString('hex'), Number(decoded[2])];
|
|
23
|
+
}
|
|
24
|
+
// -------------------------------------------------------------------------
|
|
25
|
+
describe('Method IDs', () => {
|
|
26
|
+
it('should have correct selector for delegateForUserDecryption(address,address,uint64)', () => {
|
|
27
|
+
zamaUtils_1.delegateForUserDecryptionMethodId.should.equal('0x04f61a95');
|
|
28
|
+
});
|
|
29
|
+
it('should have correct selector for multicall(bytes[])', () => {
|
|
30
|
+
zamaUtils_1.aclMulticallMethodId.should.equal('0xac9650d8');
|
|
31
|
+
});
|
|
32
|
+
it('should have correct selector for callFromParent(address,uint256,bytes)', () => {
|
|
33
|
+
zamaUtils_1.callFromParentMethodId.should.equal('0x77e60b35');
|
|
34
|
+
});
|
|
35
|
+
it('method IDs should all be distinct', () => {
|
|
36
|
+
const ids = new Set([zamaUtils_1.delegateForUserDecryptionMethodId, zamaUtils_1.aclMulticallMethodId, zamaUtils_1.callFromParentMethodId]);
|
|
37
|
+
ids.size.should.equal(3);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
// -------------------------------------------------------------------------
|
|
41
|
+
describe('buildDelegationCalldata', () => {
|
|
42
|
+
describe('output format', () => {
|
|
43
|
+
it('should produce a 0x-prefixed hex string', () => {
|
|
44
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
45
|
+
calldata.should.be.a.String();
|
|
46
|
+
calldata.should.startWith('0x');
|
|
47
|
+
});
|
|
48
|
+
it('should have exact length: 4-byte selector + 3 × 32-byte ABI words = 100 bytes (202 chars)', () => {
|
|
49
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
50
|
+
calldata.length.should.equal(202); // '0x' + 200 hex chars
|
|
51
|
+
});
|
|
52
|
+
it('should start with delegateForUserDecryption selector', () => {
|
|
53
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
54
|
+
calldata.slice(0, 10).should.equal(zamaUtils_1.delegateForUserDecryptionMethodId);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
describe('ABI parameter encoding — position and value', () => {
|
|
58
|
+
it('should encode delegate address as first ABI word (bytes 4–35)', () => {
|
|
59
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
60
|
+
// First 32-byte word after 4-byte selector = hex chars 10–74
|
|
61
|
+
const word1 = calldata.slice(10, 74);
|
|
62
|
+
word1.should.equal(DELEGATE_ADDRESS.slice(2).toLowerCase().padStart(64, '0'));
|
|
63
|
+
});
|
|
64
|
+
it('should encode token address as second ABI word (bytes 36–67)', () => {
|
|
65
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
66
|
+
const word2 = calldata.slice(74, 138);
|
|
67
|
+
word2.should.equal(TOKEN_ADDRESS.slice(2).toLowerCase().padStart(64, '0'));
|
|
68
|
+
});
|
|
69
|
+
it('should encode expiry timestamp as third ABI word (bytes 68–99)', () => {
|
|
70
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
71
|
+
const word3 = calldata.slice(138, 202);
|
|
72
|
+
const encodedExpiry = EXPIRY.toString(16).padStart(64, '0');
|
|
73
|
+
word3.should.equal(encodedExpiry);
|
|
74
|
+
});
|
|
75
|
+
it('should round-trip decode to original parameters', () => {
|
|
76
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
77
|
+
const [delegate, token, expiry] = decodeDelegationCall(calldata);
|
|
78
|
+
delegate.should.equal(DELEGATE_ADDRESS.slice(2).toLowerCase());
|
|
79
|
+
token.should.equal(TOKEN_ADDRESS.slice(2).toLowerCase());
|
|
80
|
+
expiry.should.equal(EXPIRY);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe('parameter isolation', () => {
|
|
84
|
+
it('different delegate addresses should produce different calldata', () => {
|
|
85
|
+
const DELEGATE_2 = '0x2222222222222222222222222222222222222222';
|
|
86
|
+
const c1 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
87
|
+
const c2 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_2, TOKEN_ADDRESS, EXPIRY);
|
|
88
|
+
c1.should.not.equal(c2);
|
|
89
|
+
// Only first word differs
|
|
90
|
+
c1.slice(10, 74).should.not.equal(c2.slice(10, 74));
|
|
91
|
+
c1.slice(74).should.equal(c2.slice(74)); // token and expiry unchanged
|
|
92
|
+
});
|
|
93
|
+
it('different token addresses should produce different calldata', () => {
|
|
94
|
+
const c1 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
95
|
+
const c2 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS_2, EXPIRY);
|
|
96
|
+
c1.should.not.equal(c2);
|
|
97
|
+
// Only second word differs
|
|
98
|
+
c1.slice(10, 74).should.equal(c2.slice(10, 74)); // delegate unchanged
|
|
99
|
+
c1.slice(74, 138).should.not.equal(c2.slice(74, 138));
|
|
100
|
+
c1.slice(138).should.equal(c2.slice(138)); // expiry unchanged
|
|
101
|
+
});
|
|
102
|
+
it('different expiry timestamps should produce different calldata', () => {
|
|
103
|
+
const c1 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
104
|
+
const c2 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY + 86400);
|
|
105
|
+
c1.should.not.equal(c2);
|
|
106
|
+
// Only third word differs
|
|
107
|
+
c1.slice(10, 138).should.equal(c2.slice(10, 138)); // delegate + token unchanged
|
|
108
|
+
c1.slice(138).should.not.equal(c2.slice(138));
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
describe('address case handling', () => {
|
|
112
|
+
it('should normalise checksummed (mixed-case) addresses to lowercase in encoding', () => {
|
|
113
|
+
// TOKEN_ADDRESS_3 is EIP-55 checksummed: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
|
|
114
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS_3, EXPIRY);
|
|
115
|
+
const word2 = calldata.slice(74, 138);
|
|
116
|
+
word2.should.equal(TOKEN_ADDRESS_3.slice(2).toLowerCase().padStart(64, '0'));
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
// -------------------------------------------------------------------------
|
|
121
|
+
describe('buildMulticallDelegationCalldata', () => {
|
|
122
|
+
describe('output format', () => {
|
|
123
|
+
it('should produce a 0x-prefixed hex string', () => {
|
|
124
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
125
|
+
calldata.should.be.a.String();
|
|
126
|
+
calldata.should.startWith('0x');
|
|
127
|
+
});
|
|
128
|
+
it('should start with multicall selector', () => {
|
|
129
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
130
|
+
calldata.slice(0, 10).should.equal(zamaUtils_1.aclMulticallMethodId);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe('inner call correctness', () => {
|
|
134
|
+
// Strategy: build expected inner calls independently, then verify they are
|
|
135
|
+
// embedded in the multicall payload. This avoids decoding the complex bytes[]
|
|
136
|
+
// ABI structure and directly verifies what matters: the right calls are present.
|
|
137
|
+
it('should contain the expected inner delegation call for each token', () => {
|
|
138
|
+
const inner1 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY).slice(2);
|
|
139
|
+
const inner2 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS_2, EXPIRY).slice(2);
|
|
140
|
+
const inner3 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS_3, EXPIRY).slice(2);
|
|
141
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2, TOKEN_ADDRESS_3], EXPIRY);
|
|
142
|
+
calldata.should.containEql(inner1);
|
|
143
|
+
calldata.should.containEql(inner2);
|
|
144
|
+
calldata.should.containEql(inner3);
|
|
145
|
+
});
|
|
146
|
+
it('single-token multicall should contain its inner call but not others', () => {
|
|
147
|
+
const inner1 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY).slice(2);
|
|
148
|
+
const inner2 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS_2, EXPIRY).slice(2);
|
|
149
|
+
const single = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
150
|
+
single.should.containEql(inner1);
|
|
151
|
+
single.should.not.containEql(inner2);
|
|
152
|
+
});
|
|
153
|
+
it('each inner call should start with delegateForUserDecryption selector', () => {
|
|
154
|
+
const tokens = [TOKEN_ADDRESS, TOKEN_ADDRESS_2, TOKEN_ADDRESS_3];
|
|
155
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, tokens, EXPIRY);
|
|
156
|
+
for (const token of tokens) {
|
|
157
|
+
const expectedInner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, token, EXPIRY).slice(2);
|
|
158
|
+
// Each inner call starts with delegateForUserDecryption selector
|
|
159
|
+
expectedInner.should.startWith(zamaUtils_1.delegateForUserDecryptionMethodId.slice(2));
|
|
160
|
+
calldata.should.containEql(expectedInner);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
it('different expiry timestamps change all inner calls', () => {
|
|
164
|
+
const c1 = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY);
|
|
165
|
+
const c2 = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY + 86400);
|
|
166
|
+
// Inner calls with old expiry should NOT appear in the new multicall
|
|
167
|
+
const inner1Old = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY).slice(2);
|
|
168
|
+
c2.should.not.containEql(inner1Old);
|
|
169
|
+
// And vice versa
|
|
170
|
+
const inner1New = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY + 86400).slice(2);
|
|
171
|
+
c1.should.not.containEql(inner1New);
|
|
172
|
+
});
|
|
173
|
+
it('should produce longer calldata for more tokens', () => {
|
|
174
|
+
const single = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
175
|
+
const double = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY);
|
|
176
|
+
const triple = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2, TOKEN_ADDRESS_3], EXPIRY);
|
|
177
|
+
double.length.should.be.greaterThan(single.length);
|
|
178
|
+
triple.length.should.be.greaterThan(double.length);
|
|
179
|
+
});
|
|
180
|
+
it('different token orderings should produce different calldata', () => {
|
|
181
|
+
const c1 = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY);
|
|
182
|
+
const c2 = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS_2, TOKEN_ADDRESS], EXPIRY);
|
|
183
|
+
c1.should.not.equal(c2);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
describe('error handling', () => {
|
|
187
|
+
it('should throw when given an empty token array', () => {
|
|
188
|
+
should_1.default.throws(() => (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [], EXPIRY), /tokenContractAddresses must not be empty/);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
// -------------------------------------------------------------------------
|
|
193
|
+
describe('wrapInCallFromParent', () => {
|
|
194
|
+
describe('output format', () => {
|
|
195
|
+
it('should produce a 0x-prefixed hex string', () => {
|
|
196
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
197
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
198
|
+
wrapped.should.be.a.String();
|
|
199
|
+
wrapped.should.startWith('0x');
|
|
200
|
+
});
|
|
201
|
+
it('should start with callFromParent selector', () => {
|
|
202
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
203
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
204
|
+
wrapped.slice(0, 10).should.equal(zamaUtils_1.callFromParentMethodId);
|
|
205
|
+
});
|
|
206
|
+
it('should produce longer calldata than the inner calldata', () => {
|
|
207
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
208
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(FORWARDER_ADDRESS, inner);
|
|
209
|
+
wrapped.length.should.be.greaterThan(inner.length);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
describe('ABI parameter decoding', () => {
|
|
213
|
+
it('should decode target address correctly', () => {
|
|
214
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
215
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
216
|
+
const payload = Buffer.from(wrapped.slice(10), 'hex');
|
|
217
|
+
const [target] = ethereumjs_abi_1.default.rawDecode(['address', 'uint256', 'bytes'], payload);
|
|
218
|
+
target.toString('hex').should.equal(ACL_ADDRESS.slice(2).toLowerCase());
|
|
219
|
+
});
|
|
220
|
+
it('should encode value as 0 (no ETH transfer)', () => {
|
|
221
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
222
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
223
|
+
const payload = Buffer.from(wrapped.slice(10), 'hex');
|
|
224
|
+
const [, value] = ethereumjs_abi_1.default.rawDecode(['address', 'uint256', 'bytes'], payload);
|
|
225
|
+
value.toString().should.equal('0');
|
|
226
|
+
});
|
|
227
|
+
it('should preserve inner calldata exactly', () => {
|
|
228
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
229
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
230
|
+
const payload = Buffer.from(wrapped.slice(10), 'hex');
|
|
231
|
+
const [, , data] = ethereumjs_abi_1.default.rawDecode(['address', 'uint256', 'bytes'], payload);
|
|
232
|
+
('0x' + data.toString('hex')).should.equal(inner);
|
|
233
|
+
});
|
|
234
|
+
it('should preserve multicall inner calldata exactly', () => {
|
|
235
|
+
const inner = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY);
|
|
236
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
237
|
+
const payload = Buffer.from(wrapped.slice(10), 'hex');
|
|
238
|
+
const [, , data] = ethereumjs_abi_1.default.rawDecode(['address', 'uint256', 'bytes'], payload);
|
|
239
|
+
('0x' + data.toString('hex')).should.equal(inner);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
describe('target address isolation', () => {
|
|
243
|
+
it('different target addresses should produce different calldata', () => {
|
|
244
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
245
|
+
const w1 = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
246
|
+
const w2 = (0, zamaUtils_1.wrapInCallFromParent)(FORWARDER_ADDRESS, inner);
|
|
247
|
+
w1.should.not.equal(w2);
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
// -------------------------------------------------------------------------
|
|
252
|
+
describe('buildConfidentialTransferByHandleCalldata', () => {
|
|
253
|
+
const HANDLE = '0x' + 'ab'.repeat(32); // 32-byte mock handle
|
|
254
|
+
it('should return a 0x-prefixed hex string', () => {
|
|
255
|
+
const result = (0, zamaUtils_1.buildConfidentialTransferByHandleCalldata)(DELEGATE_ADDRESS, HANDLE);
|
|
256
|
+
result.should.be.a.String();
|
|
257
|
+
result.should.startWith('0x');
|
|
258
|
+
});
|
|
259
|
+
it('should start with the confidentialTransferNoProof selector (0x5bebed7e)', () => {
|
|
260
|
+
const result = (0, zamaUtils_1.buildConfidentialTransferByHandleCalldata)(DELEGATE_ADDRESS, HANDLE);
|
|
261
|
+
result.should.startWith(walletUtil_1.confidentialTransferNoProofMethodId);
|
|
262
|
+
});
|
|
263
|
+
it('should encode the recipient address correctly', () => {
|
|
264
|
+
const result = (0, zamaUtils_1.buildConfidentialTransferByHandleCalldata)(DELEGATE_ADDRESS, HANDLE);
|
|
265
|
+
const payload = Buffer.from(result.slice(10), 'hex');
|
|
266
|
+
const decoded = ethereumjs_abi_1.default.rawDecode(['address', 'bytes32'], payload);
|
|
267
|
+
('0x' + decoded[0].toString('hex')).toLowerCase().should.equal(DELEGATE_ADDRESS.toLowerCase());
|
|
268
|
+
});
|
|
269
|
+
it('should encode the encrypted handle correctly', () => {
|
|
270
|
+
const result = (0, zamaUtils_1.buildConfidentialTransferByHandleCalldata)(DELEGATE_ADDRESS, HANDLE);
|
|
271
|
+
const payload = Buffer.from(result.slice(10), 'hex');
|
|
272
|
+
const decoded = ethereumjs_abi_1.default.rawDecode(['address', 'bytes32'], payload);
|
|
273
|
+
('0x' + decoded[1].toString('hex')).should.equal(HANDLE);
|
|
274
|
+
});
|
|
275
|
+
it('different handles should produce different calldata', () => {
|
|
276
|
+
const h1 = '0x' + '01'.repeat(32);
|
|
277
|
+
const h2 = '0x' + '02'.repeat(32);
|
|
278
|
+
(0, zamaUtils_1.buildConfidentialTransferByHandleCalldata)(DELEGATE_ADDRESS, h1).should.not.equal((0, zamaUtils_1.buildConfidentialTransferByHandleCalldata)(DELEGATE_ADDRESS, h2));
|
|
279
|
+
});
|
|
280
|
+
it('different recipient addresses should produce different calldata', () => {
|
|
281
|
+
(0, zamaUtils_1.buildConfidentialTransferByHandleCalldata)(DELEGATE_ADDRESS, HANDLE).should.not.equal((0, zamaUtils_1.buildConfidentialTransferByHandleCalldata)(TOKEN_ADDRESS, HANDLE));
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
// -------------------------------------------------------------------------
|
|
285
|
+
describe('buildFlushERC7984ForwarderTokenCalldata', () => {
|
|
286
|
+
const PARENT_ADDRESS = '0x2222222222222222222222222222222222222222';
|
|
287
|
+
const HANDLE = '0x' + 'cd'.repeat(32);
|
|
288
|
+
it('should return a 0x-prefixed hex string', () => {
|
|
289
|
+
const result = (0, zamaUtils_1.buildFlushERC7984ForwarderTokenCalldata)(TOKEN_ADDRESS, PARENT_ADDRESS, HANDLE);
|
|
290
|
+
result.should.be.a.String();
|
|
291
|
+
result.should.startWith('0x');
|
|
292
|
+
});
|
|
293
|
+
it('should start with the callFromParent selector', () => {
|
|
294
|
+
const result = (0, zamaUtils_1.buildFlushERC7984ForwarderTokenCalldata)(TOKEN_ADDRESS, PARENT_ADDRESS, HANDLE);
|
|
295
|
+
result.should.startWith(zamaUtils_1.callFromParentMethodId);
|
|
296
|
+
});
|
|
297
|
+
it('inner calldata should start with confidentialTransferNoProof selector', () => {
|
|
298
|
+
const result = (0, zamaUtils_1.buildFlushERC7984ForwarderTokenCalldata)(TOKEN_ADDRESS, PARENT_ADDRESS, HANDLE);
|
|
299
|
+
const payload = Buffer.from(result.slice(10), 'hex');
|
|
300
|
+
const decoded = ethereumjs_abi_1.default.rawDecode(['address', 'uint256', 'bytes'], payload);
|
|
301
|
+
const innerCalldata = '0x' + decoded[2].toString('hex');
|
|
302
|
+
innerCalldata.should.startWith(walletUtil_1.confidentialTransferNoProofMethodId);
|
|
303
|
+
});
|
|
304
|
+
it('outer target address should equal the token contract address', () => {
|
|
305
|
+
const result = (0, zamaUtils_1.buildFlushERC7984ForwarderTokenCalldata)(TOKEN_ADDRESS, PARENT_ADDRESS, HANDLE);
|
|
306
|
+
const payload = Buffer.from(result.slice(10), 'hex');
|
|
307
|
+
const decoded = ethereumjs_abi_1.default.rawDecode(['address', 'uint256', 'bytes'], payload);
|
|
308
|
+
('0x' + decoded[0].toString('hex')).toLowerCase().should.equal(TOKEN_ADDRESS.toLowerCase());
|
|
309
|
+
});
|
|
310
|
+
it('inner recipient should equal the parent address', () => {
|
|
311
|
+
const result = (0, zamaUtils_1.buildFlushERC7984ForwarderTokenCalldata)(TOKEN_ADDRESS, PARENT_ADDRESS, HANDLE);
|
|
312
|
+
const payload = Buffer.from(result.slice(10), 'hex');
|
|
313
|
+
const decoded = ethereumjs_abi_1.default.rawDecode(['address', 'uint256', 'bytes'], payload);
|
|
314
|
+
const innerCalldata = '0x' + decoded[2].toString('hex');
|
|
315
|
+
const innerPayload = Buffer.from(innerCalldata.slice(10), 'hex');
|
|
316
|
+
const innerDecoded = ethereumjs_abi_1.default.rawDecode(['address', 'bytes32'], innerPayload);
|
|
317
|
+
('0x' + innerDecoded[0].toString('hex')).toLowerCase().should.equal(PARENT_ADDRESS.toLowerCase());
|
|
318
|
+
});
|
|
319
|
+
it('different token addresses should produce different calldata', () => {
|
|
320
|
+
(0, zamaUtils_1.buildFlushERC7984ForwarderTokenCalldata)(TOKEN_ADDRESS, PARENT_ADDRESS, HANDLE).should.not.equal((0, zamaUtils_1.buildFlushERC7984ForwarderTokenCalldata)(TOKEN_ADDRESS_2, PARENT_ADDRESS, HANDLE));
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
// -------------------------------------------------------------------------
|
|
324
|
+
describe('decodeFlushERC7984ForwarderTokenCalldata', () => {
|
|
325
|
+
const PARENT_ADDRESS = '0x2222222222222222222222222222222222222222';
|
|
326
|
+
const HANDLE = '0x' + 'ef'.repeat(32);
|
|
327
|
+
it('should round-trip encode and decode correctly', () => {
|
|
328
|
+
const encoded = (0, zamaUtils_1.buildFlushERC7984ForwarderTokenCalldata)(TOKEN_ADDRESS, PARENT_ADDRESS, HANDLE);
|
|
329
|
+
const decoded = (0, zamaUtils_1.decodeFlushERC7984ForwarderTokenCalldata)(encoded);
|
|
330
|
+
decoded.tokenContractAddress.toLowerCase().should.equal(TOKEN_ADDRESS.toLowerCase());
|
|
331
|
+
decoded.parentAddress.toLowerCase().should.equal(PARENT_ADDRESS.toLowerCase());
|
|
332
|
+
decoded.encryptedHandle.should.equal(HANDLE);
|
|
333
|
+
});
|
|
334
|
+
it('should throw for calldata with wrong outer selector', () => {
|
|
335
|
+
const bad = '0xdeadbeef' + '00'.repeat(64);
|
|
336
|
+
should_1.default.throws(() => (0, zamaUtils_1.decodeFlushERC7984ForwarderTokenCalldata)(bad), /Invalid FlushERC7984ForwarderToken calldata/);
|
|
337
|
+
});
|
|
338
|
+
it('should throw for calldata with correct outer but wrong inner selector', () => {
|
|
339
|
+
// Wrap delegation calldata in callFromParent — inner starts with 0x04f61a95, not 0x5bebed7e
|
|
340
|
+
const innerCalldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
341
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(TOKEN_ADDRESS, innerCalldata);
|
|
342
|
+
should_1.default.throws(() => (0, zamaUtils_1.decodeFlushERC7984ForwarderTokenCalldata)(wrapped), /Invalid FlushERC7984ForwarderToken inner calldata/);
|
|
343
|
+
});
|
|
344
|
+
it('decoded tokenContractAddress should be checksummed or lowercase consistently', () => {
|
|
345
|
+
const encoded = (0, zamaUtils_1.buildFlushERC7984ForwarderTokenCalldata)(TOKEN_ADDRESS, PARENT_ADDRESS, HANDLE);
|
|
346
|
+
const decoded = (0, zamaUtils_1.decodeFlushERC7984ForwarderTokenCalldata)(encoded);
|
|
347
|
+
should_1.default.exist(decoded.tokenContractAddress);
|
|
348
|
+
decoded.tokenContractAddress.should.be.a.String();
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiemFtYVV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L3phbWFVdGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG9EQUE0QjtBQUM1QixvRUFBeUM7QUFDekMsdURBVWlDO0FBQ2pDLHlEQUErRTtBQUUvRSxRQUFRLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRTtJQUMxQixNQUFNLFdBQVcsR0FBRyw0Q0FBNEMsQ0FBQztJQUNqRSxNQUFNLGdCQUFnQixHQUFHLDRDQUE0QyxDQUFDO0lBQ3RFLE1BQU0sYUFBYSxHQUFHLDRDQUE0QyxDQUFDO0lBQ25FLE1BQU0sZUFBZSxHQUFHLDRDQUE0QyxDQUFDO0lBQ3JFLE1BQU0sZUFBZSxHQUFHLDRDQUE0QyxDQUFDO0lBQ3JFLE1BQU0saUJBQWlCLEdBQUcsNENBQTRDLENBQUM7SUFDdkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEtBQUssQ0FBQztJQUUzRCxrREFBa0Q7SUFDbEQsU0FBUyxvQkFBb0IsQ0FBQyxRQUFnQjtRQUM1QyxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkQsTUFBTSxPQUFPLEdBQUcsd0JBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxTQUFTLEVBQUUsU0FBUyxFQUFFLFFBQVEsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ2pGLE9BQU8sQ0FBRSxPQUFPLENBQUMsQ0FBQyxDQUFZLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFHLE9BQU8sQ0FBQyxDQUFDLENBQVksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFD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LEdBQUcsRUFBRSxDQUFDLElBQUEsb0RBQXdDLEVBQUMsT0FBTyxDQUFDLEVBQ3ZELG1EQUFtRCxDQUNwRCxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsOEVBQThFLEVBQUUsR0FBRyxFQUFFO1lBQ3RGLE1BQU0sT0FBTyxHQUFHLElBQUEsbURBQXVDLEVBQUMsYUFBYSxFQUFFLGNBQWMsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUMvRixNQUFNLE9BQU8sR0FBRyxJQUFBLG9EQUF3QyxFQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2xFLGdCQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1lBQzNDLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNwRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5pbXBvcnQgRXRoZXJldW1BYmkgZnJvbSAnZXRoZXJldW1qcy1hYmknO1xuaW1wb3J0IHtcbiAgYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEsXG4gIGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhLFxuICBidWlsZENvbmZpZGVudGlhbFRyYW5zZmVyQnlIYW5kbGVDYWxsZGF0YSxcbiAgYnVpbGRGbHVzaEVSQzc5ODRGb3J3YXJkZXJUb2tlbkNhbGxkYXRhLFxuICBkZWNvZGVGbHVzaEVSQzc5ODRGb3J3YXJkZXJUb2tlbkNhbGxkYXRhLFxuICB3cmFwSW5DYWxsRnJvbVBhcmVudCxcbiAgZGVsZWdhdGVGb3JVc2VyRGVjcnlwdGlvbk1ldGhvZElkLFxuICBhY2xNdWx0aWNhbGxNZXRob2RJZCxcbiAgY2FsbEZyb21QYXJlbnRNZXRob2RJZCxcbn0gZnJvbSAnLi4vLi4vc3JjL2xpYi96YW1hVXRpbHMnO1xuaW1wb3J0IHsgY29uZmlkZW50aWFsVHJhbnNmZXJOb1Byb29mTWV0aG9kSWQgfSBmcm9tICcuLi8uLi9zcmMvbGliL3dhbGxldFV0aWwnO1xuXG5kZXNjcmliZSgnWmFtYSBVdGlscycsICgpID0+IHtcbiAgY29uc3QgQUNMX0FERFJFU1MgPSAnMHhmMEZmZGM5M2I3RTE4NmJDMmY4Q0IzZEFBNzVEODZkMTkzMEE0MzNEJztcbiAgY29uc3QgREVMRUdBVEVfQUREUkVTUyA9ICcweDExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEnO1xuICBjb25zdCBUT0tFTl9BRERSRVNTID0gJzB4OTQxNjcxMjkxNzJBMzVhYjA5M0I0NGI4Yjk2MjEzRERiYzNjRDM4Nyc7XG4gIGNvbnN0IFRPS0VOX0FERFJFU1NfMiA9ICcweDRFN0IwNkQ3ODk2NTU5NGVCNUVGNTQxNGMzNTdjYTIxRTE1NTQ0OTEnO1xuICBjb25zdCBUT0tFTl9BRERSRVNTXzMgPSAnMHhBMGI4Njk5MWM2MjE4YjM2YzFkMTlENGEyZTlFYjBjRTM2MDZlQjQ4JztcbiAgY29uc3QgRk9SV0FSREVSX0FERFJFU1MgPSAnMHhEZUFEYmVlZmRFQWRiZWVmZEVhZGJFRUZkZWFkYmVFRmRFYURiZWVGJztcbiAgY29uc3QgRVhQSVJZID0gTWF0aC5mbG9vcihEYXRlLm5vdygpIC8gMTAwMCkgKyAzNjUgKiA4NjQwMDtcblxuICAvLyBIZWxwZXI6IGRlY29kZSBhIGRlbGVnYXRlRm9yVXNlckRlY3J5cHRpb24gY2FsbFxuICBmdW5jdGlvbiBkZWNvZGVEZWxlZ2F0aW9uQ2FsbChjYWxsZGF0YTogc3RyaW5nKTogW3N0cmluZywgc3RyaW5nLCBudW1iZXJdIHtcbiAgICBjb25zdCBwYXlsb2FkID0gQnVmZmVyLmZyb20oY2FsbGRhdGEuc2xpY2UoMTApLCAnaGV4Jyk7XG4gICAgY29uc3QgZGVjb2RlZCA9IEV0aGVyZXVtQWJpLnJhd0RlY29kZShbJ2FkZHJlc3MnLCAnYWRkcmVzcycsICd1aW50NjQnXSwgcGF5bG9hZCk7XG4gICAgcmV0dXJuIFsoZGVjb2RlZFswXSBhcyBCdWZmZXIpLnRvU3RyaW5nKCdoZXgnKSwgKGRlY29kZWRbMV0gYXMgQnVmZmVyKS50b1N0cmluZygnaGV4JyksIE51bWJlcihkZWNvZGVkWzJdKV07XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIGRlc2NyaWJlKCdNZXRob2QgSURzJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgaGF2ZSBjb3JyZWN0IHNlbGVjdG9yIGZvciBkZWxlZ2F0ZUZvclVzZXJEZWNyeXB0aW9uKGFkZHJlc3MsYWRkcmVzcyx1aW50NjQpJywgKCkgPT4ge1xuICAgICAgZGVsZWdhdGVGb3JVc2VyRGVjcnlwdGlvbk1ldGhvZElkLnNob3VsZC5lcXVhbCgnMHgwNGY2MWE5NScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYXZlIGNvcnJlY3Qgc2VsZWN0b3IgZm9yIG11bHRpY2FsbChieXRlc1tdKScsICgpID0+IHtcbiAgICAgIGFjbE11bHRpY2FsbE1ldGhvZElkLnNob3VsZC5lcXVhbCgnMHhhYzk2NTBkOCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYXZlIGNvcnJlY3Qgc2VsZWN0b3IgZm9yIGNhbGxGcm9tUGFyZW50KGFkZHJlc3MsdWludDI1NixieXRlcyknLCAoKSA9PiB7XG4gICAgICBjYWxsRnJvbVBhcmVudE1ldGhvZElkLnNob3VsZC5lcXVhbCgnMHg3N2U2MGIzNScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ21ldGhvZCBJRHMgc2hvdWxkIGFsbCBiZSBkaXN0aW5jdCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGlkcyA9IG5ldyBTZXQoW2RlbGVnYXRlRm9yVXNlckRlY3J5cHRpb25NZXRob2RJZCwgYWNsTXVsdGljYWxsTWV0aG9kSWQsIGNhbGxGcm9tUGFyZW50TWV0aG9kSWRdKTtcbiAgICAgIGlkcy5zaXplLnNob3VsZC5lcXVhbCgzKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICBkZXNjcmliZSgnYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEnLCAoKSA9PiB7XG4gICAgZGVzY3JpYmUoJ291dHB1dCBmb3JtYXQnLCAoKSA9PiB7XG4gICAgICBpdCgnc2hvdWxkIHByb2R1Y2UgYSAweC1wcmVmaXhlZCBoZXggc3RyaW5nJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBjYWxsZGF0YSA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNhbGxkYXRhLnNob3VsZC5iZS5hLlN0cmluZygpO1xuICAgICAgICBjYWxsZGF0YS5zaG91bGQuc3RhcnRXaXRoKCcweCcpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgaGF2ZSBleGFjdCBsZW5ndGg6IDQtYnl0ZSBzZWxlY3RvciArIDMgw5cgMzItYnl0ZSBBQkkgd29yZHMgPSAxMDAgYnl0ZXMgKDIwMiBjaGFycyknLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKTtcbiAgICAgICAgY2FsbGRhdGEubGVuZ3RoLnNob3VsZC5lcXVhbCgyMDIpOyAvLyAnMHgnICsgMjAwIGhleCBjaGFyc1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgc3RhcnQgd2l0aCBkZWxlZ2F0ZUZvclVzZXJEZWNyeXB0aW9uIHNlbGVjdG9yJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBjYWxsZGF0YSA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNhbGxkYXRhLnNsaWNlKDAsIDEwKS5zaG91bGQuZXF1YWwoZGVsZWdhdGVGb3JVc2VyRGVjcnlwdGlvbk1ldGhvZElkKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ0FCSSBwYXJhbWV0ZXIgZW5jb2Rpbmcg4oCUIHBvc2l0aW9uIGFuZCB2YWx1ZScsICgpID0+IHtcbiAgICAgIGl0KCdzaG91bGQgZW5jb2RlIGRlbGVnYXRlIGFkZHJlc3MgYXMgZmlyc3QgQUJJIHdvcmQgKGJ5dGVzIDTigJMzNSknLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKTtcbiAgICAgICAgLy8gRmlyc3QgMzItYnl0ZSB3b3JkIGFmdGVyIDQtYnl0ZSBzZWxlY3RvciA9IGhleCBjaGFycyAxMOKAkzc0XG4gICAgICAgIGNvbnN0IHdvcmQxID0gY2FsbGRhdGEuc2xpY2UoMTAsIDc0KTtcbiAgICAgICAgd29yZDEuc2hvdWxkLmVxdWFsKERFTEVHQVRFX0FERFJFU1Muc2xpY2UoMikudG9Mb3dlckNhc2UoKS5wYWRTdGFydCg2NCwgJzAnKSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBlbmNvZGUgdG9rZW4gYWRkcmVzcyBhcyBzZWNvbmQgQUJJIHdvcmQgKGJ5dGVzIDM24oCTNjcpJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBjYWxsZGF0YSA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IHdvcmQyID0gY2FsbGRhdGEuc2xpY2UoNzQsIDEzOCk7XG4gICAgICAgIHdvcmQyLnNob3VsZC5lcXVhbChUT0tFTl9BRERSRVNTLnNsaWNlKDIpLnRvTG93ZXJDYXNlKCkucGFkU3RhcnQoNjQsICcwJykpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgZW5jb2RlIGV4cGlyeSB0aW1lc3RhbXAgYXMgdGhpcmQgQUJJIHdvcmQgKGJ5dGVzIDY44oCTOTkpJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBjYWxsZGF0YSA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IHdvcmQzID0gY2FsbGRhdGEuc2xpY2UoMTM4LCAyMDIpO1xuICAgICAgICBjb25zdCBlbmNvZGVkRXhwaXJ5ID0gRVhQSVJZLnRvU3RyaW5nKDE2KS5wYWRTdGFydCg2NCwgJzAnKTtcbiAgICAgICAgd29yZDMuc2hvdWxkLmVxdWFsKGVuY29kZWRFeHBpcnkpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcm91bmQtdHJpcCBkZWNvZGUgdG8gb3JpZ2luYWwgcGFyYW1ldGVycycsICgpID0+IHtcbiAgICAgICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCBbZGVsZWdhdGUsIHRva2VuLCBleHBpcnldID0gZGVjb2RlRGVsZWdhdGlvbkNhbGwoY2FsbGRhdGEpO1xuICAgICAgICBkZWxlZ2F0ZS5zaG91bGQuZXF1YWwoREVMRUdBVEVfQUREUkVTUy5zbGljZSgyKS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgdG9rZW4uc2hvdWxkLmVxdWFsKFRPS0VOX0FERFJFU1Muc2xpY2UoMikudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgIGV4cGlyeS5zaG91bGQuZXF1YWwoRVhQSVJZKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ3BhcmFtZXRlciBpc29sYXRpb24nLCAoKSA9PiB7XG4gICAgICBpdCgnZGlmZmVyZW50IGRlbGVnYXRlIGFkZHJlc3NlcyBzaG91bGQgcHJvZHVjZSBkaWZmZXJlbnQgY2FsbGRhdGEnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IERFTEVHQVRFXzIgPSAnMHgyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyJztcbiAgICAgICAgY29uc3QgYzEgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCBjMiA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFXzIsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGMxLnNob3VsZC5ub3QuZXF1YWwoYzIpO1xuICAgICAgICAvLyBPbmx5IGZpcnN0IHdvcmQgZGlmZmVyc1xuICAgICAgICBjMS5zbGljZSgxMCwgNzQpLnNob3VsZC5ub3QuZXF1YWwoYzIuc2xpY2UoMTAsIDc0KSk7XG4gICAgICAgIGMxLnNsaWNlKDc0KS5zaG91bGQuZXF1YWwoYzIuc2xpY2UoNzQpKTsgLy8gdG9rZW4gYW5kIGV4cGlyeSB1bmNoYW5nZWRcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnZGlmZmVyZW50IHRva2VuIGFkZHJlc3NlcyBzaG91bGQgcHJvZHVjZSBkaWZmZXJlbnQgY2FsbGRhdGEnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGMxID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKTtcbiAgICAgICAgY29uc3QgYzIgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTXzIsIEVYUElSWSk7XG4gICAgICAgIGMxLnNob3VsZC5ub3QuZXF1YWwoYzIpO1xuICAgICAgICAvLyBPbmx5IHNlY29uZCB3b3JkIGRpZmZlcnNcbiAgICAgICAgYzEuc2xpY2UoMTAsIDc0KS5zaG91bGQuZXF1YWwoYzIuc2xpY2UoMTAsIDc0KSk7IC8vIGRlbGVnYXRlIHVuY2hhbmdlZFxuICAgICAgICBjMS5zbGljZSg3NCwgMTM4KS5zaG91bGQubm90LmVxdWFsKGMyLnNsaWNlKDc0LCAxMzgpKTtcbiAgICAgICAgYzEuc2xpY2UoMTM4KS5zaG91bGQuZXF1YWwoYzIuc2xpY2UoMTM4KSk7IC8vIGV4cGlyeSB1bmNoYW5nZWRcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnZGlmZmVyZW50IGV4cGlyeSB0aW1lc3RhbXBzIHNob3VsZCBwcm9kdWNlIGRpZmZlcmVudCBjYWxsZGF0YScsICgpID0+IHtcbiAgICAgICAgY29uc3QgYzEgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCBjMiA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSArIDg2NDAwKTtcbiAgICAgICAgYzEuc2hvdWxkLm5vdC5lcXVhbChjMik7XG4gICAgICAgIC8vIE9ubHkgdGhpcmQgd29yZCBkaWZmZXJzXG4gICAgICAgIGMxLnNsaWNlKDEwLCAxMzgpLnNob3VsZC5lcXVhbChjMi5zbGljZSgxMCwgMTM4KSk7IC8vIGRlbGVnYXRlICsgdG9rZW4gdW5jaGFuZ2VkXG4gICAgICAgIGMxLnNsaWNlKDEzOCkuc2hvdWxkLm5vdC5lcXVhbChjMi5zbGljZSgxMzgpKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ2FkZHJlc3MgY2FzZSBoYW5kbGluZycsICgpID0+IHtcbiAgICAgIGl0KCdzaG91bGQgbm9ybWFsaXNlIGNoZWNrc3VtbWVkIChtaXhlZC1jYXNlKSBhZGRyZXNzZXMgdG8gbG93ZXJjYXNlIGluIGVuY29kaW5nJywgKCkgPT4ge1xuICAgICAgICAvLyBUT0tFTl9BRERSRVNTXzMgaXMgRUlQLTU1IGNoZWNrc3VtbWVkOiAweEEwYjg2OTkxYzYyMThiMzZjMWQxOUQ0YTJlOUViMGNFMzYwNmVCNDhcbiAgICAgICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTXzMsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IHdvcmQyID0gY2FsbGRhdGEuc2xpY2UoNzQsIDEzOCk7XG4gICAgICAgIHdvcmQyLnNob3VsZC5lcXVhbChUT0tFTl9BRERSRVNTXzMuc2xpY2UoMikudG9Mb3dlckNhc2UoKS5wYWRTdGFydCg2NCwgJzAnKSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICBkZXNjcmliZSgnYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEnLCAoKSA9PiB7XG4gICAgZGVzY3JpYmUoJ291dHB1dCBmb3JtYXQnLCAoKSA9PiB7XG4gICAgICBpdCgnc2hvdWxkIHByb2R1Y2UgYSAweC1wcmVmaXhlZCBoZXggc3RyaW5nJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBjYWxsZGF0YSA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFtUT0tFTl9BRERSRVNTXSwgRVhQSVJZKTtcbiAgICAgICAgY2FsbGRhdGEuc2hvdWxkLmJlLmEuU3RyaW5nKCk7XG4gICAgICAgIGNhbGxkYXRhLnNob3VsZC5zdGFydFdpdGgoJzB4Jyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBzdGFydCB3aXRoIG11bHRpY2FsbCBzZWxlY3RvcicsICgpID0+IHtcbiAgICAgICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbVE9LRU5fQUREUkVTU10sIEVYUElSWSk7XG4gICAgICAgIGNhbGxkYXRhLnNsaWNlKDAsIDEwKS5zaG91bGQuZXF1YWwoYWNsTXVsdGljYWxsTWV0aG9kSWQpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnaW5uZXIgY2FsbCBjb3JyZWN0bmVzcycsICgpID0+IHtcbiAgICAgIC8vIFN0cmF0ZWd5OiBidWlsZCBleHBlY3RlZCBpbm5lciBjYWxscyBpbmRlcGVuZGVudGx5LCB0aGVuIHZlcmlmeSB0aGV5IGFyZVxuICAgICAgLy8gZW1iZWRkZWQgaW4gdGhlIG11bHRpY2FsbCBwYXlsb2FkLiBUaGlzIGF2b2lkcyBkZWNvZGluZyB0aGUgY29tcGxleCBieXRlc1tdXG4gICAgICAvLyBBQkkgc3RydWN0dXJlIGFuZCBkaXJlY3RseSB2ZXJpZmllcyB3aGF0IG1hdHRlcnM6IHRoZSByaWdodCBjYWxscyBhcmUgcHJlc2VudC5cblxuICAgICAgaXQoJ3Nob3VsZCBjb250YWluIHRoZSBleHBlY3RlZCBpbm5lciBkZWxlZ2F0aW9uIGNhbGwgZm9yIGVhY2ggdG9rZW4nLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGlubmVyMSA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSkuc2xpY2UoMik7XG4gICAgICAgIGNvbnN0IGlubmVyMiA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1NfMiwgRVhQSVJZKS5zbGljZSgyKTtcbiAgICAgICAgY29uc3QgaW5uZXIzID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTU18zLCBFWFBJUlkpLnNsaWNlKDIpO1xuXG4gICAgICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoXG4gICAgICAgICAgREVMRUdBVEVfQUREUkVTUyxcbiAgICAgICAgICBbVE9LRU5fQUREUkVTUywgVE9LRU5fQUREUkVTU18yLCBUT0tFTl9BRERSRVNTXzNdLFxuICAgICAgICAgIEVYUElSWVxuICAgICAgICApO1xuXG4gICAgICAgIGNhbGxkYXRhLnNob3VsZC5jb250YWluRXFsKGlubmVyMSk7XG4gICAgICAgIGNhbGxkYXRhLnNob3VsZC5jb250YWluRXFsKGlubmVyMik7XG4gICAgICAgIGNhbGxkYXRhLnNob3VsZC5jb250YWluRXFsKGlubmVyMyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3NpbmdsZS10b2tlbiBtdWx0aWNhbGwgc2hvdWxkIGNvbnRhaW4gaXRzIGlubmVyIGNhbGwgYnV0IG5vdCBvdGhlcnMnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGlubmVyMSA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSkuc2xpY2UoMik7XG4gICAgICAgIGNvbnN0IGlubmVyMiA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1NfMiwgRVhQSVJZKS5zbGljZSgyKTtcblxuICAgICAgICBjb25zdCBzaW5nbGUgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbVE9LRU5fQUREUkVTU10sIEVYUElSWSk7XG5cbiAgICAgICAgc2luZ2xlLnNob3VsZC5jb250YWluRXFsKGlubmVyMSk7XG4gICAgICAgIHNpbmdsZS5zaG91bGQubm90LmNvbnRhaW5FcWwoaW5uZXIyKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnZWFjaCBpbm5lciBjYWxsIHNob3VsZCBzdGFydCB3aXRoIGRlbGVnYXRlRm9yVXNlckRlY3J5cHRpb24gc2VsZWN0b3InLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHRva2VucyA9IFtUT0tFTl9BRERSRVNTLCBUT0tFTl9BRERSRVNTXzIsIFRPS0VOX0FERFJFU1NfM107XG4gICAgICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgdG9rZW5zLCBFWFBJUlkpO1xuXG4gICAgICAgIGZvciAoY29uc3QgdG9rZW4gb2YgdG9rZW5zKSB7XG4gICAgICAgICAgY29uc3QgZXhwZWN0ZWRJbm5lciA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIHRva2VuLCBFWFBJUlkpLnNsaWNlKDIpO1xuICAgICAgICAgIC8vIEVhY2ggaW5uZXIgY2FsbCBzdGFydHMgd2l0aCBkZWxlZ2F0ZUZvclVzZXJEZWNyeXB0aW9uIHNlbGVjdG9yXG4gICAgICAgICAgZXhwZWN0ZWRJbm5lci5zaG91bGQuc3RhcnRXaXRoKGRlbGVnYXRlRm9yVXNlckRlY3J5cHRpb25NZXRob2RJZC5zbGljZSgyKSk7XG4gICAgICAgICAgY2FsbGRhdGEuc2hvdWxkLmNvbnRhaW5FcWwoZXhwZWN0ZWRJbm5lcik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBpdCgnZGlmZmVyZW50IGV4cGlyeSB0aW1lc3RhbXBzIGNoYW5nZSBhbGwgaW5uZXIgY2FsbHMnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGMxID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgW1RPS0VOX0FERFJFU1MsIFRPS0VOX0FERFJFU1NfMl0sIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IGMyID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgW1RPS0VOX0FERFJFU1MsIFRPS0VOX0FERFJFU1NfMl0sIEVYUElSWSArIDg2NDAwKTtcblxuICAgICAgICAvLyBJbm5lciBjYWxscyB3aXRoIG9sZCBleHBpcnkgc2hvdWxkIE5PVCBhcHBlYXIgaW4gdGhlIG5ldyBtdWx0aWNhbGxcbiAgICAgICAgY29uc3QgaW5uZXIxT2xkID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKS5zbGljZSgyKTtcbiAgICAgICAgYzIuc2hvdWxkLm5vdC5jb250YWluRXFsKGlubmVyMU9sZCk7XG5cbiAgICAgICAgLy8gQW5kIHZpY2UgdmVyc2FcbiAgICAgICAgY29uc3QgaW5uZXIxTmV3ID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZICsgODY0MDApLnNsaWNlKDIpO1xuICAgICAgICBjMS5zaG91bGQubm90LmNvbnRhaW5FcWwoaW5uZXIxTmV3KTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHByb2R1Y2UgbG9uZ2VyIGNhbGxkYXRhIGZvciBtb3JlIHRva2VucycsICgpID0+IHtcbiAgICAgICAgY29uc3Qgc2luZ2xlID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgW1RPS0VOX0FERFJFU1NdLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCBkb3VibGUgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbVE9LRU5fQUREUkVTUywgVE9LRU5fQUREUkVTU18yXSwgRVhQSVJZKTtcbiAgICAgICAgY29uc3QgdHJpcGxlID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoXG4gICAgICAgICAgREVMRUdBVEVfQUREUkVTUyxcbiAgICAgICAgICBbVE9LRU5fQUREUkVTUywgVE9LRU5fQUREUkVTU18yLCBUT0tFTl9BRERSRVNTXzNdLFxuICAgICAgICAgIEVYUElSWVxuICAgICAgICApO1xuICAgICAgICBkb3VibGUubGVuZ3RoLnNob3VsZC5iZS5ncmVhdGVyVGhhbihzaW5nbGUubGVuZ3RoKTtcbiAgICAgICAgdHJpcGxlLmxlbmd0aC5zaG91bGQuYmUuZ3JlYXRlclRoYW4oZG91YmxlLmxlbmd0aCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ2RpZmZlcmVudCB0b2tlbiBvcmRlcmluZ3Mgc2hvdWxkIHByb2R1Y2UgZGlmZmVyZW50IGNhbGxkYXRhJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBjMSA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFtUT0tFTl9BRERSRVNTLCBUT0tFTl9BRERSRVNTXzJdLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCBjMiA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFtUT0tFTl9BRERSRVNTXzIsIFRPS0VOX0FERFJFU1NdLCBFWFBJUlkpO1xuICAgICAgICBjMS5zaG91bGQubm90LmVxdWFsKGMyKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ2Vycm9yIGhhbmRsaW5nJywgKCkgPT4ge1xuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGdpdmVuIGFuIGVtcHR5IHRva2VuIGFycmF5JywgKCkgPT4ge1xuICAgICAgICBzaG91bGQudGhyb3dzKFxuICAgICAgICAgICgpID0+IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFtdLCBFWFBJUlkpLFxuICAgICAgICAgIC90b2tlbkNvbnRyYWN0QWRkcmVzc2VzIG11c3Qgbm90IGJlIGVtcHR5L1xuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZGVzY3JpYmUoJ3dyYXBJbkNhbGxGcm9tUGFyZW50JywgKCkgPT4ge1xuICAgIGRlc2NyaWJlKCdvdXRwdXQgZm9ybWF0JywgKCkgPT4ge1xuICAgICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGEgMHgtcHJlZml4ZWQgaGV4IHN0cmluZycsICgpID0+IHtcbiAgICAgICAgY29uc3QgaW5uZXIgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCB3cmFwcGVkID0gd3JhcEluQ2FsbEZyb21QYXJlbnQoQUNMX0FERFJFU1MsIGlubmVyKTtcbiAgICAgICAgd3JhcHBlZC5zaG91bGQuYmUuYS5TdHJpbmcoKTtcbiAgICAgICAgd3JhcHBlZC5zaG91bGQuc3RhcnRXaXRoKCcweCcpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgc3RhcnQgd2l0aCBjYWxsRnJvbVBhcmVudCBzZWxlY3RvcicsICgpID0+IHtcbiAgICAgICAgY29uc3QgaW5uZXIgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCB3cmFwcGVkID0gd3JhcEluQ2FsbEZyb21QYXJlbnQoQUNMX0FERFJFU1MsIGlubmVyKTtcbiAgICAgICAgd3JhcHBlZC5zbGljZSgwLCAxMCkuc2hvdWxkLmVxdWFsKGNhbGxGcm9tUGFyZW50TWV0aG9kSWQpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcHJvZHVjZSBsb25nZXIgY2FsbGRhdGEgdGhhbiB0aGUgaW5uZXIgY2FsbGRhdGEnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGlubmVyID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKTtcbiAgICAgICAgY29uc3Qgd3JhcHBlZCA9IHdyYXBJbkNhbGxGcm9tUGFyZW50KEZPUldBUkRFUl9BRERSRVNTLCBpbm5lcik7XG4gICAgICAgIHdyYXBwZWQubGVuZ3RoLnNob3VsZC5iZS5ncmVhdGVyVGhhbihpbm5lci5sZW5ndGgpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnQUJJIHBhcmFtZXRlciBkZWNvZGluZycsICgpID0+IHtcbiAgICAgIGl0KCdzaG91bGQgZGVjb2RlIHRhcmdldCBhZGRyZXNzIGNvcnJlY3RseScsICgpID0+IHtcbiAgICAgICAgY29uc3QgaW5uZXIgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCB3cmFwcGVkID0gd3JhcEluQ2FsbEZyb21QYXJlbnQoQUNMX0FERFJFU1MsIGlubmVyKTtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IEJ1ZmZlci5mcm9tKHdyYXBwZWQuc2xpY2UoMTApLCAnaGV4Jyk7XG4gICAgICAgIGNvbnN0IFt0YXJnZXRdID0gRXRoZXJldW1BYmkucmF3RGVjb2RlKFsnYWRkcmVzcycsICd1aW50MjU2JywgJ2J5dGVzJ10sIHBheWxvYWQpO1xuICAgICAgICAodGFyZ2V0IGFzIEJ1ZmZlcikudG9TdHJpbmcoJ2hleCcpLnNob3VsZC5lcXVhbChBQ0xfQUREUkVTUy5zbGljZSgyKS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGVuY29kZSB2YWx1ZSBhcyAwIChubyBFVEggdHJhbnNmZXIpJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBpbm5lciA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IHdyYXBwZWQgPSB3cmFwSW5DYWxsRnJvbVBhcmVudChBQ0xfQUREUkVTUywgaW5uZXIpO1xuICAgICAgICBjb25zdCBwYXlsb2FkID0gQnVmZmVyLmZyb20od3JhcHBlZC5zbGljZSgxMCksICdoZXgnKTtcbiAgICAgICAgY29uc3QgWywgdmFsdWVdID0gRXRoZXJldW1BYmkucmF3RGVjb2RlKFsnYWRkcmVzcycsICd1aW50MjU2JywgJ2J5dGVzJ10sIHBheWxvYWQpO1xuICAgICAgICB2YWx1ZS50b1N0cmluZygpLnNob3VsZC5lcXVhbCgnMCcpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcHJlc2VydmUgaW5uZXIgY2FsbGRhdGEgZXhhY3RseScsICgpID0+IHtcbiAgICAgICAgY29uc3QgaW5uZXIgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCB3cmFwcGVkID0gd3JhcEluQ2FsbEZyb21QYXJlbnQoQUNMX0FERFJFU1MsIGlubmVyKTtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IEJ1ZmZlci5mcm9tKHdyYXBwZWQuc2xpY2UoMTApLCAnaGV4Jyk7XG4gICAgICAgIGNvbnN0IFssICwgZGF0YV0gPSBFdGhlcmV1bUFiaS5yYXdEZWNvZGUoWydhZGRyZXNzJywgJ3VpbnQyNTYnLCAnYnl0ZXMnXSwgcGF5bG9hZCk7XG4gICAgICAgICgnMHgnICsgKGRhdGEgYXMgQnVmZmVyKS50b1N0cmluZygnaGV4JykpLnNob3VsZC5lcXVhbChpbm5lcik7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBwcmVzZXJ2ZSBtdWx0aWNhbGwgaW5uZXIgY2FsbGRhdGEgZXhhY3RseScsICgpID0+IHtcbiAgICAgICAgY29uc3QgaW5uZXIgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbVE9LRU5fQUREUkVTUywgVE9LRU5fQUREUkVTU18yXSwgRVhQSVJZKTtcbiAgICAgICAgY29uc3Qgd3JhcHBlZCA9IHdyYXBJbkNhbGxGcm9tUGFyZW50KEFDTF9BRERSRVNTLCBpbm5lcik7XG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSBCdWZmZXIuZnJvbSh3cmFwcGVkLnNsaWNlKDEwKSwgJ2hleCcpO1xuICAgICAgICBjb25zdCBbLCAsIGRhdGFdID0gRXRoZXJldW1BYmkucmF3RGVjb2RlKFsnYWRkcmVzcycsICd1aW50MjU2JywgJ2J5dGVzJ10sIHBheWxvYWQpO1xuICAgICAgICAoJzB4JyArIChkYXRhIGFzIEJ1ZmZlcikudG9TdHJpbmcoJ2hleCcpKS5zaG91bGQuZXF1YWwoaW5uZXIpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgndGFyZ2V0IGFkZHJlc3MgaXNvbGF0aW9uJywgKCkgPT4ge1xuICAgICAgaXQoJ2RpZmZlcmVudCB0YXJnZXQgYWRkcmVzc2VzIHNob3VsZCBwcm9kdWNlIGRpZmZlcmVudCBjYWxsZGF0YScsICgpID0+IHtcbiAgICAgICAgY29uc3QgaW5uZXIgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCB3MSA9IHdyYXBJbkNhbGxGcm9tUGFyZW50KEFDTF9BRERSRVNTLCBpbm5lcik7XG4gICAgICAgIGNvbnN0IHcyID0gd3JhcEluQ2FsbEZyb21QYXJlbnQoRk9SV0FSREVSX0FERFJFU1MsIGlubmVyKTtcbiAgICAgICAgdzEuc2hvdWxkLm5vdC5lcXVhbCh3Mik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICBkZXNjcmliZSgnYnVpbGRDb25maWRlbnRpYWxUcmFuc2ZlckJ5SGFuZGxlQ2FsbGRhdGEnLCAoKSA9PiB7XG4gICAgY29uc3QgSEFORExFID0gJzB4JyArICdhYicucmVwZWF0KDMyKTsgLy8gMzItYnl0ZSBtb2NrIGhhbmRsZVxuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gYSAweC1wcmVmaXhlZCBoZXggc3RyaW5nJywgKCkgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYnVpbGRDb25maWRlbnRpYWxUcmFuc2ZlckJ5SGFuZGxlQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgSEFORExFKTtcbiAgICAgIHJlc3VsdC5zaG91bGQuYmUuYS5TdHJpbmcoKTtcbiAgICAgIHJlc3VsdC5zaG91bGQuc3RhcnRXaXRoKCcweCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzdGFydCB3aXRoIHRoZSBjb25maWRlbnRpYWxUcmFuc2Zlck5vUHJvb2Ygc2VsZWN0b3IgKDB4NWJlYmVkN2UpJywgKCkgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYnVpbGRDb25maWRlbnRpYWxUcmFuc2ZlckJ5SGFuZGxlQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgSEFORExFKTtcbiAgICAgIHJlc3VsdC5zaG91bGQuc3RhcnRXaXRoKGNvbmZpZGVudGlhbFRyYW5zZmVyTm9Qcm9vZk1ldGhvZElkKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZW5jb2RlIHRoZSByZWNpcGllbnQgYWRkcmVzcyBjb3JyZWN0bHknLCAoKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBidWlsZENvbmZpZGVudGlhbFRyYW5zZmVyQnlIYW5kbGVDYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBIQU5ETEUpO1xuICAgICAgY29uc3QgcGF5bG9hZCA9IEJ1ZmZlci5mcm9tKHJlc3VsdC5zbGljZSgxMCksICdoZXgnKTtcbiAgICAgIGNvbnN0IGRlY29kZWQgPSBFdGhlcmV1bUFiaS5yYXdEZWNvZGUoWydhZGRyZXNzJywgJ2J5dGVzMzInXSwgcGF5bG9hZCk7XG4gICAgICAoJzB4JyArIChkZWNvZGVkWzBdIGFzIEJ1ZmZlcikudG9TdHJpbmcoJ2hleCcpKS50b0xvd2VyQ2FzZSgpLnNob3VsZC5lcXVhbChERUxFR0FURV9BRERSRVNTLnRvTG93ZXJDYXNlKCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBlbmNvZGUgdGhlIGVuY3J5cHRlZCBoYW5kbGUgY29ycmVjdGx5JywgKCkgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYnVpbGRDb25maWRlbnRpYWxUcmFuc2ZlckJ5SGFuZGxlQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgSEFORExFKTtcbiAgICAgIGNvbnN0IHBheWxvYWQgPSBCdWZmZXIuZnJvbShyZXN1bHQuc2xpY2UoMTApLCAnaGV4Jyk7XG4gICAgICBjb25zdCBkZWNvZGVkID0gRXRoZXJldW1BYmkucmF3RGVjb2RlKFsnYWRkcmVzcycsICdieXRlczMyJ10sIHBheWxvYWQpO1xuICAgICAgKCcweCcgKyAoZGVjb2RlZFsxXSBhcyBCdWZmZXIpLnRvU3RyaW5nKCdoZXgnKSkuc2hvdWxkLmVxdWFsKEhBTkRMRSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZGlmZmVyZW50IGhhbmRsZXMgc2hvdWxkIHByb2R1Y2UgZGlmZmVyZW50IGNhbGxkYXRhJywgKCkgPT4ge1xuICAgICAgY29uc3QgaDEgPSAnMHgnICsgJzAxJy5yZXBlYXQoMzIpO1xuICAgICAgY29uc3QgaDIgPSAnMHgnICsgJzAyJy5yZXBlYXQoMzIpO1xuICAgICAgYnVpbGRDb25maWRlbnRpYWxUcmFuc2ZlckJ5SGFuZGxlQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgaDEpLnNob3VsZC5ub3QuZXF1YWwoXG4gICAgICAgIGJ1aWxkQ29uZmlkZW50aWFsVHJhbnNmZXJCeUhhbmRsZUNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIGgyKVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdkaWZmZXJlbnQgcmVjaXBpZW50IGFkZHJlc3NlcyBzaG91bGQgcHJvZHVjZSBkaWZmZXJlbnQgY2FsbGRhdGEnLCAoKSA9PiB7XG4gICAgICBidWlsZENvbmZpZGVudGlhbFRyYW5zZmVyQnlIYW5kbGVDYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBIQU5ETEUpLnNob3VsZC5ub3QuZXF1YWwoXG4gICAgICAgIGJ1aWxkQ29uZmlkZW50aWFsVHJhbnNmZXJCeUhhbmRsZUNhbGxkYXRhKFRPS0VOX0FERFJFU1MsIEhBTkRMRSlcbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZGVzY3JpYmUoJ2J1aWxkRmx1c2hFUkM3OTg0Rm9yd2FyZGVyVG9rZW5DYWxsZGF0YScsICgpID0+IHtcbiAgICBjb25zdCBQQVJFTlRfQUREUkVTUyA9ICcweDIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjInO1xuICAgIGNvbnN0IEhBTkRMRSA9ICcweCcgKyAnY2QnLnJlcGVhdCgzMik7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBhIDB4LXByZWZpeGVkIGhleCBzdHJpbmcnLCAoKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBidWlsZEZsdXNoRVJDNzk4NEZvcndhcmRlclRva2VuQ2FsbGRhdGEoVE9LRU5fQUREUkVTUywgUEFSRU5UX0FERFJFU1MsIEhBTkRMRSk7XG4gICAgICByZXN1bHQuc2hvdWxkLmJlLmEuU3RyaW5nKCk7XG4gICAgICByZXN1bHQuc2hvdWxkLnN0YXJ0V2l0aCgnMHgnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc3RhcnQgd2l0aCB0aGUgY2FsbEZyb21QYXJlbnQgc2VsZWN0b3InLCAoKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBidWlsZEZsdXNoRVJDNzk4NEZvcndhcmRlclRva2VuQ2FsbGRhdGEoVE9LRU5fQUREUkVTUywgUEFSRU5UX0FERFJFU1MsIEhBTkRMRSk7XG4gICAgICByZXN1bHQuc2hvdWxkLnN0YXJ0V2l0aChjYWxsRnJvbVBhcmVudE1ldGhvZElkKTtcbiAgICB9KTtcblxuICAgIGl0KCdpbm5lciBjYWxsZGF0YSBzaG91bGQgc3RhcnQgd2l0aCBjb25maWRlbnRpYWxUcmFuc2Zlck5vUHJvb2Ygc2VsZWN0b3InLCAoKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBidWlsZEZsdXNoRVJDNzk4NEZvcndhcmRlclRva2VuQ2FsbGRhdGEoVE9LRU5fQUREUkVTUywgUEFSRU5UX0FERFJFU1MsIEhBTkRMRSk7XG4gICAgICBjb25zdCBwYXlsb2FkID0gQnVmZmVyLmZyb20ocmVzdWx0LnNsaWNlKDEwKSwgJ2hleCcpO1xuICAgICAgY29uc3QgZGVjb2RlZCA9IEV0aGVyZXVtQWJpLnJhd0RlY29kZShbJ2FkZHJlc3MnLCAndWludDI1NicsICdieXRlcyddLCBwYXlsb2FkKTtcbiAgICAgIGNvbnN0IGlubmVyQ2FsbGRhdGEgPSAnMHgnICsgKGRlY29kZWRbMl0gYXMgQnVmZmVyKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBpbm5lckNhbGxkYXRhLnNob3VsZC5zdGFydFdpdGgoY29uZmlkZW50aWFsVHJhbnNmZXJOb1Byb29mTWV0aG9kSWQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ291dGVyIHRhcmdldCBhZGRyZXNzIHNob3VsZCBlcXVhbCB0aGUgdG9rZW4gY29udHJhY3QgYWRkcmVzcycsICgpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGJ1aWxkRmx1c2hFUkM3OTg0Rm9yd2FyZGVyVG9rZW5DYWxsZGF0YShUT0tFTl9BRERSRVNTLCBQQVJFTlRfQUREUkVTUywgSEFORExFKTtcbiAgICAgIGNvbnN0IHBheWxvYWQgPSBCdWZmZXIuZnJvbShyZXN1bHQuc2xpY2UoMTApLCAnaGV4Jyk7XG4gICAgICBjb25zdCBkZWNvZGVkID0gRXRoZXJldW1BYmkucmF3RGVjb2RlKFsnYWRkcmVzcycsICd1aW50MjU2JywgJ2J5dGVzJ10sIHBheWxvYWQpO1xuICAgICAgKCcweCcgKyAoZGVjb2RlZFswXSBhcyBCdWZmZXIpLnRvU3RyaW5nKCdoZXgnKSkudG9Mb3dlckNhc2UoKS5zaG91bGQuZXF1YWwoVE9LRU5fQUREUkVTUy50b0xvd2VyQ2FzZSgpKTtcbiAgICB9KTtcblxuICAgIGl0KCdpbm5lciByZWNpcGllbnQgc2hvdWxkIGVxdWFsIHRoZSBwYXJlbnQgYWRkcmVzcycsICgpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGJ1aWxkRmx1c2hFUkM3OTg0Rm9yd2FyZGVyVG9rZW5DYWxsZGF0YShUT0tFTl9BRERSRVNTLCBQQVJFTlRfQUREUkVTUywgSEFORExFKTtcbiAgICAgIGNvbnN0IHBheWxvYWQgPSBCdWZmZXIuZnJvbShyZXN1bHQuc2xpY2UoMTApLCAnaGV4Jyk7XG4gICAgICBjb25zdCBkZWNvZGVkID0gRXRoZXJldW1BYmkucmF3RGVjb2RlKFsnYWRkcmVzcycsICd1aW50MjU2JywgJ2J5dGVzJ10sIHBheWxvYWQpO1xuICAgICAgY29uc3QgaW5uZXJDYWxsZGF0YSA9ICcweCcgKyAoZGVjb2RlZFsyXSBhcyBCdWZmZXIpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGNvbnN0IGlubmVyUGF5bG9hZCA9IEJ1ZmZlci5mcm9tKGlubmVyQ2FsbGRhdGEuc2xpY2UoMTApLCAnaGV4Jyk7XG4gICAgICBjb25zdCBpbm5lckRlY29kZWQgPSBFdGhlcmV1bUFiaS5yYXdEZWNvZGUoWydhZGRyZXNzJywgJ2J5dGVzMzInXSwgaW5uZXJQYXlsb2FkKTtcbiAgICAgICgnMHgnICsgKGlubmVyRGVjb2RlZFswXSBhcyBCdWZmZXIpLnRvU3RyaW5nKCdoZXgnKSkudG9Mb3dlckNhc2UoKS5zaG91bGQuZXF1YWwoUEFSRU5UX0FERFJFU1MudG9Mb3dlckNhc2UoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZGlmZmVyZW50IHRva2VuIGFkZHJlc3NlcyBzaG91bGQgcHJvZHVjZSBkaWZmZXJlbnQgY2FsbGRhdGEnLCAoKSA9PiB7XG4gICAgICBidWlsZEZsdXNoRVJDNzk4NEZvcndhcmRlclRva2VuQ2FsbGRhdGEoVE9LRU5fQUREUkVTUywgUEFSRU5UX0FERFJFU1MsIEhBTkRMRSkuc2hvdWxkLm5vdC5lcXVhbChcbiAgICAgICAgYnVpbGRGbHVzaEVSQzc5ODRGb3J3YXJkZXJUb2tlbkNhbGxkYXRhKFRPS0VOX0FERFJFU1NfMiwgUEFSRU5UX0FERFJFU1MsIEhBTkRMRSlcbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZGVzY3JpYmUoJ2RlY29kZUZsdXNoRVJDNzk4NEZvcndhcmRlclRva2VuQ2FsbGRhdGEnLCAoKSA9PiB7XG4gICAgY29uc3QgUEFSRU5UX0FERFJFU1MgPSAnMHgyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyJztcbiAgICBjb25zdCBIQU5ETEUgPSAnMHgnICsgJ2VmJy5yZXBlYXQoMzIpO1xuXG4gICAgaXQoJ3Nob3VsZCByb3VuZC10cmlwIGVuY29kZSBhbmQgZGVjb2RlIGNvcnJlY3RseScsICgpID0+IHtcbiAgICAgIGNvbnN0IGVuY29kZWQgPSBidWlsZEZsdXNoRVJDNzk4NEZvcndhcmRlclRva2VuQ2FsbGRhdGEoVE9LRU5fQUREUkVTUywgUEFSRU5UX0FERFJFU1MsIEhBTkRMRSk7XG4gICAgICBjb25zdCBkZWNvZGVkID0gZGVjb2RlRmx1c2hFUkM3OTg0Rm9yd2FyZGVyVG9rZW5DYWxsZGF0YShlbmNvZGVkKTtcbiAgICAgIGRlY29kZWQudG9rZW5Db250cmFjdEFkZHJlc3MudG9Mb3dlckNhc2UoKS5zaG91bGQuZXF1YWwoVE9LRU5fQUREUkVTUy50b0xvd2VyQ2FzZSgpKTtcbiAgICAgIGRlY29kZWQucGFyZW50QWRkcmVzcy50b0xvd2VyQ2FzZSgpLnNob3VsZC5lcXVhbChQQVJFTlRfQUREUkVTUy50b0xvd2VyQ2FzZSgpKTtcbiAgICAgIGRlY29kZWQuZW5jcnlwdGVkSGFuZGxlLnNob3VsZC5lcXVhbChIQU5ETEUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgY2FsbGRhdGEgd2l0aCB3cm9uZyBvdXRlciBzZWxlY3RvcicsICgpID0+IHtcbiAgICAgIGNvbnN0IGJhZCA9ICcweGRlYWRiZWVmJyArICcwMCcucmVwZWF0KDY0KTtcbiAgICAgIHNob3VsZC50aHJvd3MoKCkgPT4gZGVjb2RlRmx1c2hFUkM3OTg0Rm9yd2FyZGVyVG9rZW5DYWxsZGF0YShiYWQpLCAvSW52YWxpZCBGbHVzaEVSQzc5ODRGb3J3YXJkZXJUb2tlbiBjYWxsZGF0YS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgY2FsbGRhdGEgd2l0aCBjb3JyZWN0IG91dGVyIGJ1dCB3cm9uZyBpbm5lciBzZWxlY3RvcicsICgpID0+IHtcbiAgICAgIC8vIFdyYXAgZGVsZWdhdGlvbiBjYWxsZGF0YSBpbiBjYWxsRnJvbVBhcmVudCDigJQgaW5uZXIgc3RhcnRzIHdpdGggMHgwNGY2MWE5NSwgbm90IDB4NWJlYmVkN2VcbiAgICAgIGNvbnN0IGlubmVyQ2FsbGRhdGEgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgY29uc3Qgd3JhcHBlZCA9IHdyYXBJbkNhbGxGcm9tUGFyZW50KFRPS0VOX0FERFJFU1MsIGlubmVyQ2FsbGRhdGEpO1xuICAgICAgc2hvdWxkLnRocm93cyhcbiAgICAgICAgKCkgPT4gZGVjb2RlRmx1c2hFUkM3OTg0Rm9yd2FyZGVyVG9rZW5DYWxsZGF0YSh3cmFwcGVkKSxcbiAgICAgICAgL0ludmFsaWQgRmx1c2hFUkM3OTg0Rm9yd2FyZGVyVG9rZW4gaW5uZXIgY2FsbGRhdGEvXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ2RlY29kZWQgdG9rZW5Db250cmFjdEFkZHJlc3Mgc2hvdWxkIGJlIGNoZWNrc3VtbWVkIG9yIGxvd2VyY2FzZSBjb25zaXN0ZW50bHknLCAoKSA9PiB7XG4gICAgICBjb25zdCBlbmNvZGVkID0gYnVpbGRGbHVzaEVSQzc5ODRGb3J3YXJkZXJUb2tlbkNhbGxkYXRhKFRPS0VOX0FERFJFU1MsIFBBUkVOVF9BRERSRVNTLCBIQU5ETEUpO1xuICAgICAgY29uc3QgZGVjb2RlZCA9IGRlY29kZUZsdXNoRVJDNzk4NEZvcndhcmRlclRva2VuQ2FsbGRhdGEoZW5jb2RlZCk7XG4gICAgICBzaG91bGQuZXhpc3QoZGVjb2RlZC50b2tlbkNvbnRyYWN0QWRkcmVzcyk7XG4gICAgICBkZWNvZGVkLnRva2VuQ29udHJhY3RBZGRyZXNzLnNob3VsZC5iZS5hLlN0cmluZygpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|