@bitgo-beta/abstract-eth 1.2.3-alpha.502 → 1.2.3-alpha.504
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/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/index.d.ts +2 -0
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +3 -1
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
- package/dist/src/lib/transactionBuilder.js +9 -2
- package/dist/src/lib/utils.d.ts.map +1 -1
- package/dist/src/lib/utils.js +9 -1
- package/dist/src/lib/zamaUtils.d.ts +61 -0
- package/dist/src/lib/zamaUtils.d.ts.map +1 -0
- package/dist/src/lib/zamaUtils.js +105 -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 +2 -0
- package/dist/test/unit/index.d.ts.map +1 -1
- package/dist/test/unit/index.js +3 -1
- 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/index.d.ts +1 -0
- package/dist/test/unit/transactionBuilder/index.d.ts.map +1 -1
- package/dist/test/unit/transactionBuilder/index.js +2 -1
- 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 +251 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,161 @@
|
|
|
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
|
+
exports.runDecryptionDelegationTests = runDecryptionDelegationTests;
|
|
7
|
+
/**
|
|
8
|
+
* TransactionBuilder build and rebuild tests for DecryptionDelegation transaction type.
|
|
9
|
+
*
|
|
10
|
+
* Verifies three delegation flows end-to-end through build → serialize → deserialize:
|
|
11
|
+
* Flow 1 — root wallet multicall (outer selector 0xac9650d8 → ContractCall)
|
|
12
|
+
* Flow 2 — explicit DecryptionDelegation type set by caller
|
|
13
|
+
* Flow 3 — forwarder callFromParent (outer selector 0x77e60b35 → ContractCall)
|
|
14
|
+
*/
|
|
15
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
16
|
+
const should_1 = __importDefault(require("should"));
|
|
17
|
+
const zamaUtils_1 = require("../../../src/lib/zamaUtils");
|
|
18
|
+
const utils_1 = require("../../../src/lib/utils");
|
|
19
|
+
const ACL_ADDRESS = '0xf0Ffdc93b7E186bC2f8CB3dAA75D86d1930A433D';
|
|
20
|
+
const DELEGATE_ADDRESS = '0x1111111111111111111111111111111111111111';
|
|
21
|
+
const TOKEN_ADDRESS = '0x94167129172A35ab093B44b8b96213DDbc3cD387';
|
|
22
|
+
const TOKEN_ADDRESS_2 = '0x4E7B06D78965594eB5EF5414c357ca21E1554491';
|
|
23
|
+
const FORWARDER_ADDRESS = '0xDeADbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF';
|
|
24
|
+
const EXPIRY = Math.floor(Date.now() / 1000) + 365 * 86400;
|
|
25
|
+
function runDecryptionDelegationTests(coinName, getBuilder) {
|
|
26
|
+
describe(`${coinName} transaction builder — DecryptionDelegation flows`, () => {
|
|
27
|
+
let txBuilder;
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
txBuilder = getBuilder(coinName);
|
|
30
|
+
txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
|
|
31
|
+
txBuilder.counter(1);
|
|
32
|
+
});
|
|
33
|
+
// -------------------------------------------------------------------------
|
|
34
|
+
// classifyTransaction — verify selector → type mapping
|
|
35
|
+
// -------------------------------------------------------------------------
|
|
36
|
+
describe('classifyTransaction', () => {
|
|
37
|
+
it('multicall selector (0xac9650d8) should classify as ContractCall', () => {
|
|
38
|
+
const result = (0, utils_1.classifyTransaction)(zamaUtils_1.aclMulticallMethodId + '00'.repeat(28));
|
|
39
|
+
should_1.default.equal(result, sdk_core_1.TransactionType.ContractCall);
|
|
40
|
+
});
|
|
41
|
+
it('callFromParent selector (0x77e60b35) should classify as ContractCall', () => {
|
|
42
|
+
const result = (0, utils_1.classifyTransaction)(zamaUtils_1.callFromParentMethodId + '00'.repeat(28));
|
|
43
|
+
should_1.default.equal(result, sdk_core_1.TransactionType.ContractCall);
|
|
44
|
+
});
|
|
45
|
+
it('delegateForUserDecryption selector (0x04f61a95) should classify as DecryptionDelegation', () => {
|
|
46
|
+
const result = (0, utils_1.classifyTransaction)('0x04f61a95' + '00'.repeat(28));
|
|
47
|
+
should_1.default.equal(result, sdk_core_1.TransactionType.DecryptionDelegation);
|
|
48
|
+
});
|
|
49
|
+
it('unknown selector should classify as ContractCall (fallback)', () => {
|
|
50
|
+
const result = (0, utils_1.classifyTransaction)('0xdeadbeef' + '00'.repeat(28));
|
|
51
|
+
should_1.default.equal(result, sdk_core_1.TransactionType.ContractCall);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
// -------------------------------------------------------------------------
|
|
55
|
+
// Flow 1 — root wallet multicall (outer selector = multicall → ContractCall)
|
|
56
|
+
// -------------------------------------------------------------------------
|
|
57
|
+
describe('Flow 1: root wallet multicall delegation (ContractCall type)', () => {
|
|
58
|
+
it('should build a tx with multicall delegation data', async () => {
|
|
59
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY);
|
|
60
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
61
|
+
txBuilder.contract(ACL_ADDRESS);
|
|
62
|
+
txBuilder.data(calldata);
|
|
63
|
+
const tx = await txBuilder.build();
|
|
64
|
+
const json = tx.toJson();
|
|
65
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.ContractCall);
|
|
66
|
+
json.to.should.equal(ACL_ADDRESS);
|
|
67
|
+
json.data.should.startWith(zamaUtils_1.aclMulticallMethodId);
|
|
68
|
+
json.value.should.equal('0');
|
|
69
|
+
});
|
|
70
|
+
it('should serialize and deserialize correctly (rebuild from hex)', async () => {
|
|
71
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY);
|
|
72
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
73
|
+
txBuilder.contract(ACL_ADDRESS);
|
|
74
|
+
txBuilder.data(calldata);
|
|
75
|
+
const originalTx = await txBuilder.build();
|
|
76
|
+
const rawHex = originalTx.toBroadcastFormat();
|
|
77
|
+
const rebuiltBuilder = getBuilder(coinName);
|
|
78
|
+
rebuiltBuilder.from(rawHex);
|
|
79
|
+
const rebuiltTx = await rebuiltBuilder.build();
|
|
80
|
+
should_1.default.equal(rebuiltTx.toBroadcastFormat(), rawHex);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
// -------------------------------------------------------------------------
|
|
84
|
+
// Flow 2 — explicit DecryptionDelegation type (WP sets this for TSS path)
|
|
85
|
+
// -------------------------------------------------------------------------
|
|
86
|
+
describe('Flow 2: explicit DecryptionDelegation type', () => {
|
|
87
|
+
it('should build a DecryptionDelegation tx', async () => {
|
|
88
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
89
|
+
txBuilder.type(sdk_core_1.TransactionType.DecryptionDelegation);
|
|
90
|
+
txBuilder.contract(ACL_ADDRESS);
|
|
91
|
+
txBuilder.data(calldata);
|
|
92
|
+
const tx = await txBuilder.build();
|
|
93
|
+
const json = tx.toJson();
|
|
94
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.DecryptionDelegation);
|
|
95
|
+
json.to.should.equal(ACL_ADDRESS);
|
|
96
|
+
json.data.should.startWith(zamaUtils_1.aclMulticallMethodId);
|
|
97
|
+
});
|
|
98
|
+
it('should serialize and deserialize correctly (rebuild from hex)', async () => {
|
|
99
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
100
|
+
txBuilder.type(sdk_core_1.TransactionType.DecryptionDelegation);
|
|
101
|
+
txBuilder.contract(ACL_ADDRESS);
|
|
102
|
+
txBuilder.data(calldata);
|
|
103
|
+
const originalTx = await txBuilder.build();
|
|
104
|
+
const rawHex = originalTx.toBroadcastFormat();
|
|
105
|
+
// from() classifies via outer selector (multicall → ContractCall) and rebuilds correctly
|
|
106
|
+
const rebuiltBuilder = getBuilder(coinName);
|
|
107
|
+
rebuiltBuilder.from(rawHex);
|
|
108
|
+
const rebuiltTx = await rebuiltBuilder.build();
|
|
109
|
+
should_1.default.equal(rebuiltTx.toBroadcastFormat(), rawHex);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
// -------------------------------------------------------------------------
|
|
113
|
+
// Flow 3 — forwarder callFromParent (outer selector = callFromParent → ContractCall)
|
|
114
|
+
// -------------------------------------------------------------------------
|
|
115
|
+
describe('Flow 3: forwarder callFromParent delegation (ContractCall type)', () => {
|
|
116
|
+
it('should build a tx targeting the forwarder with callFromParent data', async () => {
|
|
117
|
+
const innerCalldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
118
|
+
const outerCalldata = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, innerCalldata);
|
|
119
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
120
|
+
txBuilder.contract(FORWARDER_ADDRESS);
|
|
121
|
+
txBuilder.data(outerCalldata);
|
|
122
|
+
const tx = await txBuilder.build();
|
|
123
|
+
const json = tx.toJson();
|
|
124
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.ContractCall);
|
|
125
|
+
// outer tx targets the forwarder, not the ACL
|
|
126
|
+
json.to.should.equal(FORWARDER_ADDRESS);
|
|
127
|
+
json.data.should.startWith(zamaUtils_1.callFromParentMethodId);
|
|
128
|
+
});
|
|
129
|
+
it('should serialize and deserialize correctly (rebuild from hex)', async () => {
|
|
130
|
+
const innerCalldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
131
|
+
const outerCalldata = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, innerCalldata);
|
|
132
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
133
|
+
txBuilder.contract(FORWARDER_ADDRESS);
|
|
134
|
+
txBuilder.data(outerCalldata);
|
|
135
|
+
const originalTx = await txBuilder.build();
|
|
136
|
+
const rawHex = originalTx.toBroadcastFormat();
|
|
137
|
+
const rebuiltBuilder = getBuilder(coinName);
|
|
138
|
+
rebuiltBuilder.from(rawHex);
|
|
139
|
+
const rebuiltTx = await rebuiltBuilder.build();
|
|
140
|
+
should_1.default.equal(rebuiltTx.toBroadcastFormat(), rawHex);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
// -------------------------------------------------------------------------
|
|
144
|
+
// Validation
|
|
145
|
+
// -------------------------------------------------------------------------
|
|
146
|
+
describe('validation', () => {
|
|
147
|
+
it('should throw if contract address is missing for DecryptionDelegation', async () => {
|
|
148
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
149
|
+
txBuilder.type(sdk_core_1.TransactionType.DecryptionDelegation);
|
|
150
|
+
txBuilder.data(calldata);
|
|
151
|
+
await txBuilder.build().should.be.rejectedWith('Invalid transaction: missing contract address');
|
|
152
|
+
});
|
|
153
|
+
it('should throw if data is missing for DecryptionDelegation', async () => {
|
|
154
|
+
txBuilder.type(sdk_core_1.TransactionType.DecryptionDelegation);
|
|
155
|
+
txBuilder.contract(ACL_ADDRESS);
|
|
156
|
+
await txBuilder.build().should.be.rejectedWith('Invalid transaction: missing contract call data field');
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjcnlwdGlvbkRlbGVnYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90ZXN0L3VuaXQvdHJhbnNhY3Rpb25CdWlsZGVyL2RlY3J5cHRpb25EZWxlZ2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBMEJBLG9FQXFLQztBQS9MRDs7Ozs7OztHQU9HO0FBQ0gsbURBQXVEO0FBQ3ZELG9EQUE0QjtBQUU1QiwwREFLb0M7QUFDcEMsa0RBQTZEO0FBRTdELE1BQU0sV0FBVyxHQUFHLDRDQUE0QyxDQUFDO0FBQ2pFLE1BQU0sZ0JBQWdCLEdBQUcsNENBQTRDLENBQUM7QUFDdEUsTUFBTSxhQUFhLEdBQUcsNENBQTRDLENBQUM7QUFDbkUsTUFBTSxlQUFlLEdBQUcsNENBQTRDLENBQUM7QUFDckUsTUFBTSxpQkFBaUIsR0FBRyw0Q0FBNEMsQ0FBQztBQUN2RSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsS0FBSyxDQUFDO0FBRTNELFNBQWdCLDRCQUE0QixDQUFDLFFBQWdCLEVBQUUsVUFBZ0Q7SUFDN0csUUFBUSxDQUFDLEdBQUcsUUFBUSxtREFBbUQsRUFBRSxHQUFHLEVBQUU7UUFDNUUsSUFBSSxTQUE2QixDQUFDO1FBRWxDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxTQUFTLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2pDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBQ3pELFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkIsQ0FBQyxDQUFDLENBQUM7UUFFSCw0RUFBNEU7UUFDNUUsdURBQXVEO1FBQ3ZELDRFQUE0RTtRQUM1RSxRQUFRLENBQUMscUJBQXFC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LEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ3hFLFNBQVMsQ0FBQyxJQUFJLENBQUMsMEJBQWUsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO2dCQUNyRCxTQUFTLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUNoQyxNQUFNLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyx1REFBdUQsQ0FBQyxDQUFDO1lBQzFHLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFRyYW5zYWN0aW9uQnVpbGRlciBidWlsZCBhbmQgcmVidWlsZCB0ZXN0cyBmb3IgRGVjcnlwdGlvbkRlbGVnYXRpb24gdHJhbnNhY3Rpb24gdHlwZS5cbiAqXG4gKiBWZXJpZmllcyB0aHJlZSBkZWxlZ2F0aW9uIGZsb3dzIGVuZC10by1lbmQgdGhyb3VnaCBidWlsZCDihpIgc2VyaWFsaXplIOKGkiBkZXNlcmlhbGl6ZTpcbiAqICAgRmxvdyAxIOKAlCByb290IHdhbGxldCBtdWx0aWNhbGwgKG91dGVyIHNlbGVjdG9yIDB4YWM5NjUwZDgg4oaSIENvbnRyYWN0Q2FsbClcbiAqICAgRmxvdyAyIOKAlCBleHBsaWNpdCBEZWNyeXB0aW9uRGVsZWdhdGlvbiB0eXBlIHNldCBieSBjYWxsZXJcbiAqICAgRmxvdyAzIOKAlCBmb3J3YXJkZXIgY2FsbEZyb21QYXJlbnQgKG91dGVyIHNlbGVjdG9yIDB4NzdlNjBiMzUg4oaSIENvbnRyYWN0Q2FsbClcbiAqL1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25UeXBlIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHNob3VsZCBmcm9tICdzaG91bGQnO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25CdWlsZGVyIH0gZnJvbSAnLi4vLi4vLi4vc3JjJztcbmltcG9ydCB7XG4gIGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhLFxuICB3cmFwSW5DYWxsRnJvbVBhcmVudCxcbiAgYWNsTXVsdGljYWxsTWV0aG9kSWQsXG4gIGNhbGxGcm9tUGFyZW50TWV0aG9kSWQsXG59IGZyb20gJy4uLy4uLy4uL3NyYy9saWIvemFtYVV0aWxzJztcbmltcG9ydCB7IGNsYXNzaWZ5VHJhbnNhY3Rpb24gfSBmcm9tICcuLi8uLi8uLi9zcmMvbGliL3V0aWxzJztcblxuY29uc3QgQUNMX0FERFJFU1MgPSAnMHhmMEZmZGM5M2I3RTE4NmJDMmY4Q0IzZEFBNzVEODZkMTkzMEE0MzNEJztcbmNvbnN0IERFTEVHQVRFX0FERFJFU1MgPSAnMHgxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExJztcbmNvbnN0IFRPS0VOX0FERFJFU1MgPSAnMHg5NDE2NzEyOTE3MkEzNWFiMDkzQjQ0YjhiOTYyMTNERGJjM2NEMzg3JztcbmNvbnN0IFRPS0VOX0FERFJFU1NfMiA9ICcweDRFN0IwNkQ3ODk2NTU5NGVCNUVGNTQxNGMzNTdjYTIxRTE1NTQ0OTEnO1xuY29uc3QgRk9SV0FSREVSX0FERFJFU1MgPSAnMHhEZUFEYmVlZmRFQWRiZWVmZEVhZGJFRUZkZWFkYmVFRmRFYURiZWVGJztcbmNvbnN0IEVYUElSWSA9IE1hdGguZmxvb3IoRGF0ZS5ub3coKSAvIDEwMDApICsgMzY1ICogODY0MDA7XG5cbmV4cG9ydCBmdW5jdGlvbiBydW5EZWNyeXB0aW9uRGVsZWdhdGlvblRlc3RzKGNvaW5OYW1lOiBzdHJpbmcsIGdldEJ1aWxkZXI6IChjb2luOiBzdHJpbmcpID0+IFRyYW5zYWN0aW9uQnVpbGRlcik6IHZvaWQge1xuICBkZXNjcmliZShgJHtjb2luTmFtZX0gdHJhbnNhY3Rpb24gYnVpbGRlciDigJQgRGVjcnlwdGlvbkRlbGVnYXRpb24gZmxvd3NgLCAoKSA9PiB7XG4gICAgbGV0IHR4QnVpbGRlcjogVHJhbnNhY3Rpb25CdWlsZGVyO1xuXG4gICAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgICB0eEJ1aWxkZXIgPSBnZXRCdWlsZGVyKGNvaW5OYW1lKTtcbiAgICAgIHR4QnVpbGRlci5mZWUoeyBmZWU6ICcxMDAwMDAwMDAwJywgZ2FzTGltaXQ6ICcyMDAwMDAnIH0pO1xuICAgICAgdHhCdWlsZGVyLmNvdW50ZXIoMSk7XG4gICAgfSk7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gY2xhc3NpZnlUcmFuc2FjdGlvbiDigJQgdmVyaWZ5IHNlbGVjdG9yIOKGkiB0eXBlIG1hcHBpbmdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgZGVzY3JpYmUoJ2NsYXNzaWZ5VHJhbnNhY3Rpb24nLCAoKSA9PiB7XG4gICAgICBpdCgnbXVsdGljYWxsIHNlbGVjdG9yICgweGFjOTY1MGQ4KSBzaG91bGQgY2xhc3NpZnkgYXMgQ29udHJhY3RDYWxsJywgKCkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBjbGFzc2lmeVRyYW5zYWN0aW9uKGFjbE11bHRpY2FsbE1ldGhvZElkICsgJzAwJy5yZXBlYXQoMjgpKTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKHJlc3VsdCwgVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ2NhbGxGcm9tUGFyZW50IHNlbGVjdG9yICgweDc3ZTYwYjM1KSBzaG91bGQgY2xhc3NpZnkgYXMgQ29udHJhY3RDYWxsJywgKCkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBjbGFzc2lmeVRyYW5zYWN0aW9uKGNhbGxGcm9tUGFyZW50TWV0aG9kSWQgKyAnMDAnLnJlcGVhdCgyOCkpO1xuICAgICAgICBzaG91bGQuZXF1YWwocmVzdWx0LCBUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnZGVsZWdhdGVGb3JVc2VyRGVjcnlwdGlvbiBzZWxlY3RvciAoMHgwNGY2MWE5NSkgc2hvdWxkIGNsYXNzaWZ5IGFzIERlY3J5cHRpb25EZWxlZ2F0aW9uJywgKCkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBjbGFzc2lmeVRyYW5zYWN0aW9uKCcweDA0ZjYxYTk1JyArICcwMCcucmVwZWF0KDI4KSk7XG4gICAgICAgIHNob3VsZC5lcXVhbChyZXN1bHQsIFRyYW5zYWN0aW9uVHlwZS5EZWNyeXB0aW9uRGVsZWdhdGlvbik7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Vua25vd24gc2VsZWN0b3Igc2hvdWxkIGNsYXNzaWZ5IGFzIENvbnRyYWN0Q2FsbCAoZmFsbGJhY2spJywgKCkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBjbGFzc2lmeVRyYW5zYWN0aW9uKCcweGRlYWRiZWVmJyArICcwMCcucmVwZWF0KDI4KSk7XG4gICAgICAgIHNob3VsZC5lcXVhbChyZXN1bHQsIFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGwpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gRmxvdyAxIOKAlCByb290IHdhbGxldCBtdWx0aWNhbGwgKG91dGVyIHNlbGVjdG9yID0gbXVsdGljYWxsIOKGkiBDb250cmFjdENhbGwpXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGRlc2NyaWJlKCdGbG93IDE6IHJvb3Qgd2FsbGV0IG11bHRpY2FsbCBkZWxlZ2F0aW9uIChDb250cmFjdENhbGwgdHlwZSknLCAoKSA9PiB7XG4gICAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgdHggd2l0aCBtdWx0aWNhbGwgZGVsZWdhdGlvbiBkYXRhJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBjYWxsZGF0YSA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFtUT0tFTl9BRERSRVNTLCBUT0tFTl9BRERSRVNTXzJdLCBFWFBJUlkpO1xuICAgICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgICAgICAgdHhCdWlsZGVyLmNvbnRyYWN0KEFDTF9BRERSRVNTKTtcbiAgICAgICAgdHhCdWlsZGVyLmRhdGEoY2FsbGRhdGEpO1xuXG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIGNvbnN0IGpzb24gPSB0eC50b0pzb24oKTtcblxuICAgICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCk7XG4gICAgICAgIGpzb24udG8uc2hvdWxkLmVxdWFsKEFDTF9BRERSRVNTKTtcbiAgICAgICAganNvbi5kYXRhLnNob3VsZC5zdGFydFdpdGgoYWNsTXVsdGljYWxsTWV0aG9kSWQpO1xuICAgICAgICBqc29uLnZhbHVlLnNob3VsZC5lcXVhbCgnMCcpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZSBjb3JyZWN0bHkgKHJlYnVpbGQgZnJvbSBoZXgpJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBjYWxsZGF0YSA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFtUT0tFTl9BRERSRVNTLCBUT0tFTl9BRERSRVNTXzJdLCBFWFBJUlkpO1xuICAgICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgICAgICAgdHhCdWlsZGVyLmNvbnRyYWN0KEFDTF9BRERSRVNTKTtcbiAgICAgICAgdHhCdWlsZGVyLmRhdGEoY2FsbGRhdGEpO1xuXG4gICAgICAgIGNvbnN0IG9yaWdpbmFsVHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgY29uc3QgcmF3SGV4ID0gb3JpZ2luYWxUeC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgICAgIGNvbnN0IHJlYnVpbHRCdWlsZGVyID0gZ2V0QnVpbGRlcihjb2luTmFtZSk7XG4gICAgICAgIHJlYnVpbHRCdWlsZGVyLmZyb20ocmF3SGV4KTtcbiAgICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsdEJ1aWxkZXIuYnVpbGQoKTtcblxuICAgICAgICBzaG91bGQuZXF1YWwocmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksIHJhd0hleCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBGbG93IDIg4oCUIGV4cGxpY2l0IERlY3J5cHRpb25EZWxlZ2F0aW9uIHR5cGUgKFdQIHNldHMgdGhpcyBmb3IgVFNTIHBhdGgpXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGRlc2NyaWJlKCdGbG93IDI6IGV4cGxpY2l0IERlY3J5cHRpb25EZWxlZ2F0aW9uIHR5cGUnLCAoKSA9PiB7XG4gICAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgRGVjcnlwdGlvbkRlbGVnYXRpb24gdHgnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgW1RPS0VOX0FERFJFU1NdLCBFWFBJUlkpO1xuICAgICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuRGVjcnlwdGlvbkRlbGVnYXRpb24pO1xuICAgICAgICB0eEJ1aWxkZXIuY29udHJhY3QoQUNMX0FERFJFU1MpO1xuICAgICAgICB0eEJ1aWxkZXIuZGF0YShjYWxsZGF0YSk7XG5cbiAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgY29uc3QganNvbiA9IHR4LnRvSnNvbigpO1xuXG4gICAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuRGVjcnlwdGlvbkRlbGVnYXRpb24pO1xuICAgICAgICBqc29uLnRvLnNob3VsZC5lcXVhbChBQ0xfQUREUkVTUyk7XG4gICAgICAgIGpzb24uZGF0YS5zaG91bGQuc3RhcnRXaXRoKGFjbE11bHRpY2FsbE1ldGhvZElkKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHNlcmlhbGl6ZSBhbmQgZGVzZXJpYWxpemUgY29ycmVjdGx5IChyZWJ1aWxkIGZyb20gaGV4KScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbVE9LRU5fQUREUkVTU10sIEVYUElSWSk7XG4gICAgICAgIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5EZWNyeXB0aW9uRGVsZWdhdGlvbik7XG4gICAgICAgIHR4QnVpbGRlci5jb250cmFjdChBQ0xfQUREUkVTUyk7XG4gICAgICAgIHR4QnVpbGRlci5kYXRhKGNhbGxkYXRhKTtcblxuICAgICAgICBjb25zdCBvcmlnaW5hbFR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIGNvbnN0IHJhd0hleCA9IG9yaWdpbmFsVHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgICAvLyBmcm9tKCkgY2xhc3NpZmllcyB2aWEgb3V0ZXIgc2VsZWN0b3IgKG11bHRpY2FsbCDihpIgQ29udHJhY3RDYWxsKSBhbmQgcmVidWlsZHMgY29ycmVjdGx5XG4gICAgICAgIGNvbnN0IHJlYnVpbHRCdWlsZGVyID0gZ2V0QnVpbGRlcihjb2luTmFtZSk7XG4gICAgICAgIHJlYnVpbHRCdWlsZGVyLmZyb20ocmF3SGV4KTtcbiAgICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsdEJ1aWxkZXIuYnVpbGQoKTtcblxuICAgICAgICBzaG91bGQuZXF1YWwocmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksIHJhd0hleCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBGbG93IDMg4oCUIGZvcndhcmRlciBjYWxsRnJvbVBhcmVudCAob3V0ZXIgc2VsZWN0b3IgPSBjYWxsRnJvbVBhcmVudCDihpIgQ29udHJhY3RDYWxsKVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBkZXNjcmliZSgnRmxvdyAzOiBmb3J3YXJkZXIgY2FsbEZyb21QYXJlbnQgZGVsZWdhdGlvbiAoQ29udHJhY3RDYWxsIHR5cGUpJywgKCkgPT4ge1xuICAgICAgaXQoJ3Nob3VsZCBidWlsZCBhIHR4IHRhcmdldGluZyB0aGUgZm9yd2FyZGVyIHdpdGggY2FsbEZyb21QYXJlbnQgZGF0YScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgaW5uZXJDYWxsZGF0YSA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFtUT0tFTl9BRERSRVNTXSwgRVhQSVJZKTtcbiAgICAgICAgY29uc3Qgb3V0ZXJDYWxsZGF0YSA9IHdyYXBJbkNhbGxGcm9tUGFyZW50KEFDTF9BRERSRVNTLCBpbm5lckNhbGxkYXRhKTtcblxuICAgICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgICAgICAgdHhCdWlsZGVyLmNvbnRyYWN0KEZPUldBUkRFUl9BRERSRVNTKTtcbiAgICAgICAgdHhCdWlsZGVyLmRhdGEob3V0ZXJDYWxsZGF0YSk7XG5cbiAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgY29uc3QganNvbiA9IHR4LnRvSnNvbigpO1xuXG4gICAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgICAgICAgLy8gb3V0ZXIgdHggdGFyZ2V0cyB0aGUgZm9yd2FyZGVyLCBub3QgdGhlIEFDTFxuICAgICAgICBqc29uLnRvLnNob3VsZC5lcXVhbChGT1JXQVJERVJfQUREUkVTUyk7XG4gICAgICAgIGpzb24uZGF0YS5zaG91bGQuc3RhcnRXaXRoKGNhbGxGcm9tUGFyZW50TWV0aG9kSWQpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZSBjb3JyZWN0bHkgKHJlYnVpbGQgZnJvbSBoZXgpJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBpbm5lckNhbGxkYXRhID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgW1RPS0VOX0FERFJFU1NdLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCBvdXRlckNhbGxkYXRhID0gd3JhcEluQ2FsbEZyb21QYXJlbnQoQUNMX0FERFJFU1MsIGlubmVyQ2FsbGRhdGEpO1xuXG4gICAgICAgIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGwpO1xuICAgICAgICB0eEJ1aWxkZXIuY29udHJhY3QoRk9SV0FSREVSX0FERFJFU1MpO1xuICAgICAgICB0eEJ1aWxkZXIuZGF0YShvdXRlckNhbGxkYXRhKTtcblxuICAgICAgICBjb25zdCBvcmlnaW5hbFR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIGNvbnN0IHJhd0hleCA9IG9yaWdpbmFsVHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgICBjb25zdCByZWJ1aWx0QnVpbGRlciA9IGdldEJ1aWxkZXIoY29pbk5hbWUpO1xuICAgICAgICByZWJ1aWx0QnVpbGRlci5mcm9tKHJhd0hleCk7XG4gICAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbHRCdWlsZGVyLmJ1aWxkKCk7XG5cbiAgICAgICAgc2hvdWxkLmVxdWFsKHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLCByYXdIZXgpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gVmFsaWRhdGlvblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBkZXNjcmliZSgndmFsaWRhdGlvbicsICgpID0+IHtcbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgY29udHJhY3QgYWRkcmVzcyBpcyBtaXNzaW5nIGZvciBEZWNyeXB0aW9uRGVsZWdhdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbVE9LRU5fQUREUkVTU10sIEVYUElSWSk7XG4gICAgICAgIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5EZWNyeXB0aW9uRGVsZWdhdGlvbik7XG4gICAgICAgIHR4QnVpbGRlci5kYXRhKGNhbGxkYXRhKTtcbiAgICAgICAgYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnSW52YWxpZCB0cmFuc2FjdGlvbjogbWlzc2luZyBjb250cmFjdCBhZGRyZXNzJyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiBkYXRhIGlzIG1pc3NpbmcgZm9yIERlY3J5cHRpb25EZWxlZ2F0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuRGVjcnlwdGlvbkRlbGVnYXRpb24pO1xuICAgICAgICB0eEJ1aWxkZXIuY29udHJhY3QoQUNMX0FERFJFU1MpO1xuICAgICAgICBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIGNvbnRyYWN0IGNhbGwgZGF0YSBmaWVsZCcpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xufVxuIl19
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../test/unit/transactionBuilder/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,QAAQ,CAAC;AACvB,cAAc,wBAAwB,CAAC;AACvC,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../test/unit/transactionBuilder/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,QAAQ,CAAC;AACvB,cAAc,wBAAwB,CAAC;AACvC,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC"}
|
|
@@ -18,4 +18,5 @@ __exportStar(require("./addressInitialization"), exports);
|
|
|
18
18
|
__exportStar(require("./send"), exports);
|
|
19
19
|
__exportStar(require("./walletInitialization"), exports);
|
|
20
20
|
__exportStar(require("./flushNft"), exports);
|
|
21
|
-
|
|
21
|
+
__exportStar(require("./decryptionDelegation"), exports);
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90ZXN0L3VuaXQvdHJhbnNhY3Rpb25CdWlsZGVyL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwwREFBd0M7QUFDeEMseUNBQXVCO0FBQ3ZCLHlEQUF1QztBQUN2Qyw2Q0FBMkI7QUFDM0IseURBQXVDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9hZGRyZXNzSW5pdGlhbGl6YXRpb24nO1xuZXhwb3J0ICogZnJvbSAnLi9zZW5kJztcbmV4cG9ydCAqIGZyb20gJy4vd2FsbGV0SW5pdGlhbGl6YXRpb24nO1xuZXhwb3J0ICogZnJvbSAnLi9mbHVzaE5mdCc7XG5leHBvcnQgKiBmcm9tICcuL2RlY3J5cHRpb25EZWxlZ2F0aW9uJztcbiJdfQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zamaUtils.d.ts","sourceRoot":"","sources":["../../../test/unit/zamaUtils.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,251 @@
|
|
|
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
|
+
describe('Zama Utils', () => {
|
|
10
|
+
const ACL_ADDRESS = '0xf0Ffdc93b7E186bC2f8CB3dAA75D86d1930A433D';
|
|
11
|
+
const DELEGATE_ADDRESS = '0x1111111111111111111111111111111111111111';
|
|
12
|
+
const TOKEN_ADDRESS = '0x94167129172A35ab093B44b8b96213DDbc3cD387';
|
|
13
|
+
const TOKEN_ADDRESS_2 = '0x4E7B06D78965594eB5EF5414c357ca21E1554491';
|
|
14
|
+
const TOKEN_ADDRESS_3 = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
|
|
15
|
+
const FORWARDER_ADDRESS = '0xDeADbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF';
|
|
16
|
+
const EXPIRY = Math.floor(Date.now() / 1000) + 365 * 86400;
|
|
17
|
+
// Helper: decode a delegateForUserDecryption call
|
|
18
|
+
function decodeDelegationCall(calldata) {
|
|
19
|
+
const payload = Buffer.from(calldata.slice(10), 'hex');
|
|
20
|
+
const decoded = ethereumjs_abi_1.default.rawDecode(['address', 'address', 'uint64'], payload);
|
|
21
|
+
return [decoded[0].toString('hex'), decoded[1].toString('hex'), Number(decoded[2])];
|
|
22
|
+
}
|
|
23
|
+
// -------------------------------------------------------------------------
|
|
24
|
+
describe('Method IDs', () => {
|
|
25
|
+
it('should have correct selector for delegateForUserDecryption(address,address,uint64)', () => {
|
|
26
|
+
zamaUtils_1.delegateForUserDecryptionMethodId.should.equal('0x04f61a95');
|
|
27
|
+
});
|
|
28
|
+
it('should have correct selector for multicall(bytes[])', () => {
|
|
29
|
+
zamaUtils_1.aclMulticallMethodId.should.equal('0xac9650d8');
|
|
30
|
+
});
|
|
31
|
+
it('should have correct selector for callFromParent(address,uint256,bytes)', () => {
|
|
32
|
+
zamaUtils_1.callFromParentMethodId.should.equal('0x77e60b35');
|
|
33
|
+
});
|
|
34
|
+
it('method IDs should all be distinct', () => {
|
|
35
|
+
const ids = new Set([zamaUtils_1.delegateForUserDecryptionMethodId, zamaUtils_1.aclMulticallMethodId, zamaUtils_1.callFromParentMethodId]);
|
|
36
|
+
ids.size.should.equal(3);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
// -------------------------------------------------------------------------
|
|
40
|
+
describe('buildDelegationCalldata', () => {
|
|
41
|
+
describe('output format', () => {
|
|
42
|
+
it('should produce a 0x-prefixed hex string', () => {
|
|
43
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
44
|
+
calldata.should.be.a.String();
|
|
45
|
+
calldata.should.startWith('0x');
|
|
46
|
+
});
|
|
47
|
+
it('should have exact length: 4-byte selector + 3 × 32-byte ABI words = 100 bytes (202 chars)', () => {
|
|
48
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
49
|
+
calldata.length.should.equal(202); // '0x' + 200 hex chars
|
|
50
|
+
});
|
|
51
|
+
it('should start with delegateForUserDecryption selector', () => {
|
|
52
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
53
|
+
calldata.slice(0, 10).should.equal(zamaUtils_1.delegateForUserDecryptionMethodId);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('ABI parameter encoding — position and value', () => {
|
|
57
|
+
it('should encode delegate address as first ABI word (bytes 4–35)', () => {
|
|
58
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
59
|
+
// First 32-byte word after 4-byte selector = hex chars 10–74
|
|
60
|
+
const word1 = calldata.slice(10, 74);
|
|
61
|
+
word1.should.equal(DELEGATE_ADDRESS.slice(2).toLowerCase().padStart(64, '0'));
|
|
62
|
+
});
|
|
63
|
+
it('should encode token address as second ABI word (bytes 36–67)', () => {
|
|
64
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
65
|
+
const word2 = calldata.slice(74, 138);
|
|
66
|
+
word2.should.equal(TOKEN_ADDRESS.slice(2).toLowerCase().padStart(64, '0'));
|
|
67
|
+
});
|
|
68
|
+
it('should encode expiry timestamp as third ABI word (bytes 68–99)', () => {
|
|
69
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
70
|
+
const word3 = calldata.slice(138, 202);
|
|
71
|
+
const encodedExpiry = EXPIRY.toString(16).padStart(64, '0');
|
|
72
|
+
word3.should.equal(encodedExpiry);
|
|
73
|
+
});
|
|
74
|
+
it('should round-trip decode to original parameters', () => {
|
|
75
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
76
|
+
const [delegate, token, expiry] = decodeDelegationCall(calldata);
|
|
77
|
+
delegate.should.equal(DELEGATE_ADDRESS.slice(2).toLowerCase());
|
|
78
|
+
token.should.equal(TOKEN_ADDRESS.slice(2).toLowerCase());
|
|
79
|
+
expiry.should.equal(EXPIRY);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe('parameter isolation', () => {
|
|
83
|
+
it('different delegate addresses should produce different calldata', () => {
|
|
84
|
+
const DELEGATE_2 = '0x2222222222222222222222222222222222222222';
|
|
85
|
+
const c1 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
86
|
+
const c2 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_2, TOKEN_ADDRESS, EXPIRY);
|
|
87
|
+
c1.should.not.equal(c2);
|
|
88
|
+
// Only first word differs
|
|
89
|
+
c1.slice(10, 74).should.not.equal(c2.slice(10, 74));
|
|
90
|
+
c1.slice(74).should.equal(c2.slice(74)); // token and expiry unchanged
|
|
91
|
+
});
|
|
92
|
+
it('different token addresses should produce different calldata', () => {
|
|
93
|
+
const c1 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
94
|
+
const c2 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS_2, EXPIRY);
|
|
95
|
+
c1.should.not.equal(c2);
|
|
96
|
+
// Only second word differs
|
|
97
|
+
c1.slice(10, 74).should.equal(c2.slice(10, 74)); // delegate unchanged
|
|
98
|
+
c1.slice(74, 138).should.not.equal(c2.slice(74, 138));
|
|
99
|
+
c1.slice(138).should.equal(c2.slice(138)); // expiry unchanged
|
|
100
|
+
});
|
|
101
|
+
it('different expiry timestamps should produce different calldata', () => {
|
|
102
|
+
const c1 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
103
|
+
const c2 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY + 86400);
|
|
104
|
+
c1.should.not.equal(c2);
|
|
105
|
+
// Only third word differs
|
|
106
|
+
c1.slice(10, 138).should.equal(c2.slice(10, 138)); // delegate + token unchanged
|
|
107
|
+
c1.slice(138).should.not.equal(c2.slice(138));
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe('address case handling', () => {
|
|
111
|
+
it('should normalise checksummed (mixed-case) addresses to lowercase in encoding', () => {
|
|
112
|
+
// TOKEN_ADDRESS_3 is EIP-55 checksummed: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
|
|
113
|
+
const calldata = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS_3, EXPIRY);
|
|
114
|
+
const word2 = calldata.slice(74, 138);
|
|
115
|
+
word2.should.equal(TOKEN_ADDRESS_3.slice(2).toLowerCase().padStart(64, '0'));
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
// -------------------------------------------------------------------------
|
|
120
|
+
describe('buildMulticallDelegationCalldata', () => {
|
|
121
|
+
describe('output format', () => {
|
|
122
|
+
it('should produce a 0x-prefixed hex string', () => {
|
|
123
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
124
|
+
calldata.should.be.a.String();
|
|
125
|
+
calldata.should.startWith('0x');
|
|
126
|
+
});
|
|
127
|
+
it('should start with multicall selector', () => {
|
|
128
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
129
|
+
calldata.slice(0, 10).should.equal(zamaUtils_1.aclMulticallMethodId);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe('inner call correctness', () => {
|
|
133
|
+
// Strategy: build expected inner calls independently, then verify they are
|
|
134
|
+
// embedded in the multicall payload. This avoids decoding the complex bytes[]
|
|
135
|
+
// ABI structure and directly verifies what matters: the right calls are present.
|
|
136
|
+
it('should contain the expected inner delegation call for each token', () => {
|
|
137
|
+
const inner1 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY).slice(2);
|
|
138
|
+
const inner2 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS_2, EXPIRY).slice(2);
|
|
139
|
+
const inner3 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS_3, EXPIRY).slice(2);
|
|
140
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2, TOKEN_ADDRESS_3], EXPIRY);
|
|
141
|
+
calldata.should.containEql(inner1);
|
|
142
|
+
calldata.should.containEql(inner2);
|
|
143
|
+
calldata.should.containEql(inner3);
|
|
144
|
+
});
|
|
145
|
+
it('single-token multicall should contain its inner call but not others', () => {
|
|
146
|
+
const inner1 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY).slice(2);
|
|
147
|
+
const inner2 = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS_2, EXPIRY).slice(2);
|
|
148
|
+
const single = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
149
|
+
single.should.containEql(inner1);
|
|
150
|
+
single.should.not.containEql(inner2);
|
|
151
|
+
});
|
|
152
|
+
it('each inner call should start with delegateForUserDecryption selector', () => {
|
|
153
|
+
const tokens = [TOKEN_ADDRESS, TOKEN_ADDRESS_2, TOKEN_ADDRESS_3];
|
|
154
|
+
const calldata = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, tokens, EXPIRY);
|
|
155
|
+
for (const token of tokens) {
|
|
156
|
+
const expectedInner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, token, EXPIRY).slice(2);
|
|
157
|
+
// Each inner call starts with delegateForUserDecryption selector
|
|
158
|
+
expectedInner.should.startWith(zamaUtils_1.delegateForUserDecryptionMethodId.slice(2));
|
|
159
|
+
calldata.should.containEql(expectedInner);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
it('different expiry timestamps change all inner calls', () => {
|
|
163
|
+
const c1 = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY);
|
|
164
|
+
const c2 = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY + 86400);
|
|
165
|
+
// Inner calls with old expiry should NOT appear in the new multicall
|
|
166
|
+
const inner1Old = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY).slice(2);
|
|
167
|
+
c2.should.not.containEql(inner1Old);
|
|
168
|
+
// And vice versa
|
|
169
|
+
const inner1New = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY + 86400).slice(2);
|
|
170
|
+
c1.should.not.containEql(inner1New);
|
|
171
|
+
});
|
|
172
|
+
it('should produce longer calldata for more tokens', () => {
|
|
173
|
+
const single = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS], EXPIRY);
|
|
174
|
+
const double = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY);
|
|
175
|
+
const triple = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2, TOKEN_ADDRESS_3], EXPIRY);
|
|
176
|
+
double.length.should.be.greaterThan(single.length);
|
|
177
|
+
triple.length.should.be.greaterThan(double.length);
|
|
178
|
+
});
|
|
179
|
+
it('different token orderings should produce different calldata', () => {
|
|
180
|
+
const c1 = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY);
|
|
181
|
+
const c2 = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS_2, TOKEN_ADDRESS], EXPIRY);
|
|
182
|
+
c1.should.not.equal(c2);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
describe('error handling', () => {
|
|
186
|
+
it('should throw when given an empty token array', () => {
|
|
187
|
+
should_1.default.throws(() => (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [], EXPIRY), /tokenContractAddresses must not be empty/);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
// -------------------------------------------------------------------------
|
|
192
|
+
describe('wrapInCallFromParent', () => {
|
|
193
|
+
describe('output format', () => {
|
|
194
|
+
it('should produce a 0x-prefixed hex string', () => {
|
|
195
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
196
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
197
|
+
wrapped.should.be.a.String();
|
|
198
|
+
wrapped.should.startWith('0x');
|
|
199
|
+
});
|
|
200
|
+
it('should start with callFromParent selector', () => {
|
|
201
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
202
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
203
|
+
wrapped.slice(0, 10).should.equal(zamaUtils_1.callFromParentMethodId);
|
|
204
|
+
});
|
|
205
|
+
it('should produce longer calldata than the inner calldata', () => {
|
|
206
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
207
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(FORWARDER_ADDRESS, inner);
|
|
208
|
+
wrapped.length.should.be.greaterThan(inner.length);
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
describe('ABI parameter decoding', () => {
|
|
212
|
+
it('should decode target address correctly', () => {
|
|
213
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
214
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
215
|
+
const payload = Buffer.from(wrapped.slice(10), 'hex');
|
|
216
|
+
const [target] = ethereumjs_abi_1.default.rawDecode(['address', 'uint256', 'bytes'], payload);
|
|
217
|
+
target.toString('hex').should.equal(ACL_ADDRESS.slice(2).toLowerCase());
|
|
218
|
+
});
|
|
219
|
+
it('should encode value as 0 (no ETH transfer)', () => {
|
|
220
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
221
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
222
|
+
const payload = Buffer.from(wrapped.slice(10), 'hex');
|
|
223
|
+
const [, value] = ethereumjs_abi_1.default.rawDecode(['address', 'uint256', 'bytes'], payload);
|
|
224
|
+
value.toString().should.equal('0');
|
|
225
|
+
});
|
|
226
|
+
it('should preserve inner calldata exactly', () => {
|
|
227
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
228
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
229
|
+
const payload = Buffer.from(wrapped.slice(10), 'hex');
|
|
230
|
+
const [, , data] = ethereumjs_abi_1.default.rawDecode(['address', 'uint256', 'bytes'], payload);
|
|
231
|
+
('0x' + data.toString('hex')).should.equal(inner);
|
|
232
|
+
});
|
|
233
|
+
it('should preserve multicall inner calldata exactly', () => {
|
|
234
|
+
const inner = (0, zamaUtils_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [TOKEN_ADDRESS, TOKEN_ADDRESS_2], EXPIRY);
|
|
235
|
+
const wrapped = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
236
|
+
const payload = Buffer.from(wrapped.slice(10), 'hex');
|
|
237
|
+
const [, , data] = ethereumjs_abi_1.default.rawDecode(['address', 'uint256', 'bytes'], payload);
|
|
238
|
+
('0x' + data.toString('hex')).should.equal(inner);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
describe('target address isolation', () => {
|
|
242
|
+
it('different target addresses should produce different calldata', () => {
|
|
243
|
+
const inner = (0, zamaUtils_1.buildDelegationCalldata)(DELEGATE_ADDRESS, TOKEN_ADDRESS, EXPIRY);
|
|
244
|
+
const w1 = (0, zamaUtils_1.wrapInCallFromParent)(ACL_ADDRESS, inner);
|
|
245
|
+
const w2 = (0, zamaUtils_1.wrapInCallFromParent)(FORWARDER_ADDRESS, inner);
|
|
246
|
+
w1.should.not.equal(w2);
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiemFtYVV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L3phbWFVdGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG9EQUE0QjtBQUM1QixvRUFBeUM7QUFDekMsdURBT2lDO0FBRWpDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsR0FBRyxFQUFFO0lBQzFCLE1BQU0sV0FBVyxHQUFHLDRDQUE0QyxDQUFDO0lBQ2pFLE1BQU0sZ0JBQWdCLEdBQUcsNENBQTRDLENBQUM7SUFDdEUsTUFBTSxhQUFhLEdBQUcsNENBQTRDLENBQUM7SUFDbkUsTUFBTSxlQUFlLEdBQUcsNENBQTRDLENBQUM7SUFDckUsTUFBTSxlQUFlLEdBQUcsNENBQTRDLENBQUM7SUFDckUsTUFBTSxpQkFBaUIsR0FBRyw0Q0FBNEMsQ0FBQztJQUN2RSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsS0FBSyxDQUFDO0lBRTNELGtEQUFrRDtJQUNsRCxTQUFTLG9CQUFvQixDQUFDLFFBQWdCO1FBQzVDLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN2RCxNQUFNLE9BQU8sR0FBRyx3QkFBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDakYsT0FBTyxDQUFFLE9BQU8sQ0FBQyxDQUFDLENBQVksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUcsT0FBTyxDQUFDLENBQUMsQ0FBWSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5RyxD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QUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBzaG91bGQgZnJvbSAnc2hvdWxkJztcbmltcG9ydCBFdGhlcmV1bUFiaSBmcm9tICdldGhlcmV1bWpzLWFiaSc7XG5pbXBvcnQge1xuICBidWlsZERlbGVnYXRpb25DYWxsZGF0YSxcbiAgYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEsXG4gIHdyYXBJbkNhbGxGcm9tUGFyZW50LFxuICBkZWxlZ2F0ZUZvclVzZXJEZWNyeXB0aW9uTWV0aG9kSWQsXG4gIGFjbE11bHRpY2FsbE1ldGhvZElkLFxuICBjYWxsRnJvbVBhcmVudE1ldGhvZElkLFxufSBmcm9tICcuLi8uLi9zcmMvbGliL3phbWFVdGlscyc7XG5cbmRlc2NyaWJlKCdaYW1hIFV0aWxzJywgKCkgPT4ge1xuICBjb25zdCBBQ0xfQUREUkVTUyA9ICcweGYwRmZkYzkzYjdFMTg2YkMyZjhDQjNkQUE3NUQ4NmQxOTMwQTQzM0QnO1xuICBjb25zdCBERUxFR0FURV9BRERSRVNTID0gJzB4MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMSc7XG4gIGNvbnN0IFRPS0VOX0FERFJFU1MgPSAnMHg5NDE2NzEyOTE3MkEzNWFiMDkzQjQ0YjhiOTYyMTNERGJjM2NEMzg3JztcbiAgY29uc3QgVE9LRU5fQUREUkVTU18yID0gJzB4NEU3QjA2RDc4OTY1NTk0ZUI1RUY1NDE0YzM1N2NhMjFFMTU1NDQ5MSc7XG4gIGNvbnN0IFRPS0VOX0FERFJFU1NfMyA9ICcweEEwYjg2OTkxYzYyMThiMzZjMWQxOUQ0YTJlOUViMGNFMzYwNmVCNDgnO1xuICBjb25zdCBGT1JXQVJERVJfQUREUkVTUyA9ICcweERlQURiZWVmZEVBZGJlZWZkRWFkYkVFRmRlYWRiZUVGZEVhRGJlZUYnO1xuICBjb25zdCBFWFBJUlkgPSBNYXRoLmZsb29yKERhdGUubm93KCkgLyAxMDAwKSArIDM2NSAqIDg2NDAwO1xuXG4gIC8vIEhlbHBlcjogZGVjb2RlIGEgZGVsZWdhdGVGb3JVc2VyRGVjcnlwdGlvbiBjYWxsXG4gIGZ1bmN0aW9uIGRlY29kZURlbGVnYXRpb25DYWxsKGNhbGxkYXRhOiBzdHJpbmcpOiBbc3RyaW5nLCBzdHJpbmcsIG51bWJlcl0ge1xuICAgIGNvbnN0IHBheWxvYWQgPSBCdWZmZXIuZnJvbShjYWxsZGF0YS5zbGljZSgxMCksICdoZXgnKTtcbiAgICBjb25zdCBkZWNvZGVkID0gRXRoZXJldW1BYmkucmF3RGVjb2RlKFsnYWRkcmVzcycsICdhZGRyZXNzJywgJ3VpbnQ2NCddLCBwYXlsb2FkKTtcbiAgICByZXR1cm4gWyhkZWNvZGVkWzBdIGFzIEJ1ZmZlcikudG9TdHJpbmcoJ2hleCcpLCAoZGVjb2RlZFsxXSBhcyBCdWZmZXIpLnRvU3RyaW5nKCdoZXgnKSwgTnVtYmVyKGRlY29kZWRbMl0pXTtcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZGVzY3JpYmUoJ01ldGhvZCBJRHMnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBoYXZlIGNvcnJlY3Qgc2VsZWN0b3IgZm9yIGRlbGVnYXRlRm9yVXNlckRlY3J5cHRpb24oYWRkcmVzcyxhZGRyZXNzLHVpbnQ2NCknLCAoKSA9PiB7XG4gICAgICBkZWxlZ2F0ZUZvclVzZXJEZWNyeXB0aW9uTWV0aG9kSWQuc2hvdWxkLmVxdWFsKCcweDA0ZjYxYTk1Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhdmUgY29ycmVjdCBzZWxlY3RvciBmb3IgbXVsdGljYWxsKGJ5dGVzW10pJywgKCkgPT4ge1xuICAgICAgYWNsTXVsdGljYWxsTWV0aG9kSWQuc2hvdWxkLmVxdWFsKCcweGFjOTY1MGQ4Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhdmUgY29ycmVjdCBzZWxlY3RvciBmb3IgY2FsbEZyb21QYXJlbnQoYWRkcmVzcyx1aW50MjU2LGJ5dGVzKScsICgpID0+IHtcbiAgICAgIGNhbGxGcm9tUGFyZW50TWV0aG9kSWQuc2hvdWxkLmVxdWFsKCcweDc3ZTYwYjM1Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnbWV0aG9kIElEcyBzaG91bGQgYWxsIGJlIGRpc3RpbmN0JywgKCkgPT4ge1xuICAgICAgY29uc3QgaWRzID0gbmV3IFNldChbZGVsZWdhdGVGb3JVc2VyRGVjcnlwdGlvbk1ldGhvZElkLCBhY2xNdWx0aWNhbGxNZXRob2RJZCwgY2FsbEZyb21QYXJlbnRNZXRob2RJZF0pO1xuICAgICAgaWRzLnNpemUuc2hvdWxkLmVxdWFsKDMpO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIGRlc2NyaWJlKCdidWlsZERlbGVnYXRpb25DYWxsZGF0YScsICgpID0+IHtcbiAgICBkZXNjcmliZSgnb3V0cHV0IGZvcm1hdCcsICgpID0+IHtcbiAgICAgIGl0KCdzaG91bGQgcHJvZHVjZSBhIDB4LXByZWZpeGVkIGhleCBzdHJpbmcnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKTtcbiAgICAgICAgY2FsbGRhdGEuc2hvdWxkLmJlLmEuU3RyaW5nKCk7XG4gICAgICAgIGNhbGxkYXRhLnNob3VsZC5zdGFydFdpdGgoJzB4Jyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBoYXZlIGV4YWN0IGxlbmd0aDogNC1ieXRlIHNlbGVjdG9yICsgMyDDlyAzMi1ieXRlIEFCSSB3b3JkcyA9IDEwMCBieXRlcyAoMjAyIGNoYXJzKScsICgpID0+IHtcbiAgICAgICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICBjYWxsZGF0YS5sZW5ndGguc2hvdWxkLmVxdWFsKDIwMik7IC8vICcweCcgKyAyMDAgaGV4IGNoYXJzXG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBzdGFydCB3aXRoIGRlbGVnYXRlRm9yVXNlckRlY3J5cHRpb24gc2VsZWN0b3InLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKTtcbiAgICAgICAgY2FsbGRhdGEuc2xpY2UoMCwgMTApLnNob3VsZC5lcXVhbChkZWxlZ2F0ZUZvclVzZXJEZWNyeXB0aW9uTWV0aG9kSWQpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnQUJJIHBhcmFtZXRlciBlbmNvZGluZyDigJQgcG9zaXRpb24gYW5kIHZhbHVlJywgKCkgPT4ge1xuICAgICAgaXQoJ3Nob3VsZCBlbmNvZGUgZGVsZWdhdGUgYWRkcmVzcyBhcyBmaXJzdCBBQkkgd29yZCAoYnl0ZXMgNOKAkzM1KScsICgpID0+IHtcbiAgICAgICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICAvLyBGaXJzdCAzMi1ieXRlIHdvcmQgYWZ0ZXIgNC1ieXRlIHNlbGVjdG9yID0gaGV4IGNoYXJzIDEw4oCTNzRcbiAgICAgICAgY29uc3Qgd29yZDEgPSBjYWxsZGF0YS5zbGljZSgxMCwgNzQpO1xuICAgICAgICB3b3JkMS5zaG91bGQuZXF1YWwoREVMRUdBVEVfQUREUkVTUy5zbGljZSgyKS50b0xvd2VyQ2FzZSgpLnBhZFN0YXJ0KDY0LCAnMCcpKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGVuY29kZSB0b2tlbiBhZGRyZXNzIGFzIHNlY29uZCBBQkkgd29yZCAoYnl0ZXMgMzbigJM2NyknLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKTtcbiAgICAgICAgY29uc3Qgd29yZDIgPSBjYWxsZGF0YS5zbGljZSg3NCwgMTM4KTtcbiAgICAgICAgd29yZDIuc2hvdWxkLmVxdWFsKFRPS0VOX0FERFJFU1Muc2xpY2UoMikudG9Mb3dlckNhc2UoKS5wYWRTdGFydCg2NCwgJzAnKSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBlbmNvZGUgZXhwaXJ5IHRpbWVzdGFtcCBhcyB0aGlyZCBBQkkgd29yZCAoYnl0ZXMgNjjigJM5OSknLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKTtcbiAgICAgICAgY29uc3Qgd29yZDMgPSBjYWxsZGF0YS5zbGljZSgxMzgsIDIwMik7XG4gICAgICAgIGNvbnN0IGVuY29kZWRFeHBpcnkgPSBFWFBJUlkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDY0LCAnMCcpO1xuICAgICAgICB3b3JkMy5zaG91bGQuZXF1YWwoZW5jb2RlZEV4cGlyeSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCByb3VuZC10cmlwIGRlY29kZSB0byBvcmlnaW5hbCBwYXJhbWV0ZXJzJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBjYWxsZGF0YSA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IFtkZWxlZ2F0ZSwgdG9rZW4sIGV4cGlyeV0gPSBkZWNvZGVEZWxlZ2F0aW9uQ2FsbChjYWxsZGF0YSk7XG4gICAgICAgIGRlbGVnYXRlLnNob3VsZC5lcXVhbChERUxFR0FURV9BRERSRVNTLnNsaWNlKDIpLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgICB0b2tlbi5zaG91bGQuZXF1YWwoVE9LRU5fQUREUkVTUy5zbGljZSgyKS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgZXhwaXJ5LnNob3VsZC5lcXVhbChFWFBJUlkpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgncGFyYW1ldGVyIGlzb2xhdGlvbicsICgpID0+IHtcbiAgICAgIGl0KCdkaWZmZXJlbnQgZGVsZWdhdGUgYWRkcmVzc2VzIHNob3VsZCBwcm9kdWNlIGRpZmZlcmVudCBjYWxsZGF0YScsICgpID0+IHtcbiAgICAgICAgY29uc3QgREVMRUdBVEVfMiA9ICcweDIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjInO1xuICAgICAgICBjb25zdCBjMSA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IGMyID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfMiwgVE9LRU5fQUREUkVTUywgRVhQSVJZKTtcbiAgICAgICAgYzEuc2hvdWxkLm5vdC5lcXVhbChjMik7XG4gICAgICAgIC8vIE9ubHkgZmlyc3Qgd29yZCBkaWZmZXJzXG4gICAgICAgIGMxLnNsaWNlKDEwLCA3NCkuc2hvdWxkLm5vdC5lcXVhbChjMi5zbGljZSgxMCwgNzQpKTtcbiAgICAgICAgYzEuc2xpY2UoNzQpLnNob3VsZC5lcXVhbChjMi5zbGljZSg3NCkpOyAvLyB0b2tlbiBhbmQgZXhwaXJ5IHVuY2hhbmdlZFxuICAgICAgfSk7XG5cbiAgICAgIGl0KCdkaWZmZXJlbnQgdG9rZW4gYWRkcmVzc2VzIHNob3VsZCBwcm9kdWNlIGRpZmZlcmVudCBjYWxsZGF0YScsICgpID0+IHtcbiAgICAgICAgY29uc3QgYzEgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCBjMiA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1NfMiwgRVhQSVJZKTtcbiAgICAgICAgYzEuc2hvdWxkLm5vdC5lcXVhbChjMik7XG4gICAgICAgIC8vIE9ubHkgc2Vjb25kIHdvcmQgZGlmZmVyc1xuICAgICAgICBjMS5zbGljZSgxMCwgNzQpLnNob3VsZC5lcXVhbChjMi5zbGljZSgxMCwgNzQpKTsgLy8gZGVsZWdhdGUgdW5jaGFuZ2VkXG4gICAgICAgIGMxLnNsaWNlKDc0LCAxMzgpLnNob3VsZC5ub3QuZXF1YWwoYzIuc2xpY2UoNzQsIDEzOCkpO1xuICAgICAgICBjMS5zbGljZSgxMzgpLnNob3VsZC5lcXVhbChjMi5zbGljZSgxMzgpKTsgLy8gZXhwaXJ5IHVuY2hhbmdlZFxuICAgICAgfSk7XG5cbiAgICAgIGl0KCdkaWZmZXJlbnQgZXhwaXJ5IHRpbWVzdGFtcHMgc2hvdWxkIHByb2R1Y2UgZGlmZmVyZW50IGNhbGxkYXRhJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBjMSA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IGMyID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZICsgODY0MDApO1xuICAgICAgICBjMS5zaG91bGQubm90LmVxdWFsKGMyKTtcbiAgICAgICAgLy8gT25seSB0aGlyZCB3b3JkIGRpZmZlcnNcbiAgICAgICAgYzEuc2xpY2UoMTAsIDEzOCkuc2hvdWxkLmVxdWFsKGMyLnNsaWNlKDEwLCAxMzgpKTsgLy8gZGVsZWdhdGUgKyB0b2tlbiB1bmNoYW5nZWRcbiAgICAgICAgYzEuc2xpY2UoMTM4KS5zaG91bGQubm90LmVxdWFsKGMyLnNsaWNlKDEzOCkpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnYWRkcmVzcyBjYXNlIGhhbmRsaW5nJywgKCkgPT4ge1xuICAgICAgaXQoJ3Nob3VsZCBub3JtYWxpc2UgY2hlY2tzdW1tZWQgKG1peGVkLWNhc2UpIGFkZHJlc3NlcyB0byBsb3dlcmNhc2UgaW4gZW5jb2RpbmcnLCAoKSA9PiB7XG4gICAgICAgIC8vIFRPS0VOX0FERFJFU1NfMyBpcyBFSVAtNTUgY2hlY2tzdW1tZWQ6IDB4QTBiODY5OTFjNjIxOGIzNmMxZDE5RDRhMmU5RWIwY0UzNjA2ZUI0OFxuICAgICAgICBjb25zdCBjYWxsZGF0YSA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1NfMywgRVhQSVJZKTtcbiAgICAgICAgY29uc3Qgd29yZDIgPSBjYWxsZGF0YS5zbGljZSg3NCwgMTM4KTtcbiAgICAgICAgd29yZDIuc2hvdWxkLmVxdWFsKFRPS0VOX0FERFJFU1NfMy5zbGljZSgyKS50b0xvd2VyQ2FzZSgpLnBhZFN0YXJ0KDY0LCAnMCcpKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIGRlc2NyaWJlKCdidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YScsICgpID0+IHtcbiAgICBkZXNjcmliZSgnb3V0cHV0IGZvcm1hdCcsICgpID0+IHtcbiAgICAgIGl0KCdzaG91bGQgcHJvZHVjZSBhIDB4LXByZWZpeGVkIGhleCBzdHJpbmcnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgW1RPS0VOX0FERFJFU1NdLCBFWFBJUlkpO1xuICAgICAgICBjYWxsZGF0YS5zaG91bGQuYmUuYS5TdHJpbmcoKTtcbiAgICAgICAgY2FsbGRhdGEuc2hvdWxkLnN0YXJ0V2l0aCgnMHgnKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHN0YXJ0IHdpdGggbXVsdGljYWxsIHNlbGVjdG9yJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBjYWxsZGF0YSA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFtUT0tFTl9BRERSRVNTXSwgRVhQSVJZKTtcbiAgICAgICAgY2FsbGRhdGEuc2xpY2UoMCwgMTApLnNob3VsZC5lcXVhbChhY2xNdWx0aWNhbGxNZXRob2RJZCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdpbm5lciBjYWxsIGNvcnJlY3RuZXNzJywgKCkgPT4ge1xuICAgICAgLy8gU3RyYXRlZ3k6IGJ1aWxkIGV4cGVjdGVkIGlubmVyIGNhbGxzIGluZGVwZW5kZW50bHksIHRoZW4gdmVyaWZ5IHRoZXkgYXJlXG4gICAgICAvLyBlbWJlZGRlZCBpbiB0aGUgbXVsdGljYWxsIHBheWxvYWQuIFRoaXMgYXZvaWRzIGRlY29kaW5nIHRoZSBjb21wbGV4IGJ5dGVzW11cbiAgICAgIC8vIEFCSSBzdHJ1Y3R1cmUgYW5kIGRpcmVjdGx5IHZlcmlmaWVzIHdoYXQgbWF0dGVyczogdGhlIHJpZ2h0IGNhbGxzIGFyZSBwcmVzZW50LlxuXG4gICAgICBpdCgnc2hvdWxkIGNvbnRhaW4gdGhlIGV4cGVjdGVkIGlubmVyIGRlbGVnYXRpb24gY2FsbCBmb3IgZWFjaCB0b2tlbicsICgpID0+IHtcbiAgICAgICAgY29uc3QgaW5uZXIxID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKS5zbGljZSgyKTtcbiAgICAgICAgY29uc3QgaW5uZXIyID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTU18yLCBFWFBJUlkpLnNsaWNlKDIpO1xuICAgICAgICBjb25zdCBpbm5lcjMgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTXzMsIEVYUElSWSkuc2xpY2UoMik7XG5cbiAgICAgICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShcbiAgICAgICAgICBERUxFR0FURV9BRERSRVNTLFxuICAgICAgICAgIFtUT0tFTl9BRERSRVNTLCBUT0tFTl9BRERSRVNTXzIsIFRPS0VOX0FERFJFU1NfM10sXG4gICAgICAgICAgRVhQSVJZXG4gICAgICAgICk7XG5cbiAgICAgICAgY2FsbGRhdGEuc2hvdWxkLmNvbnRhaW5FcWwoaW5uZXIxKTtcbiAgICAgICAgY2FsbGRhdGEuc2hvdWxkLmNvbnRhaW5FcWwoaW5uZXIyKTtcbiAgICAgICAgY2FsbGRhdGEuc2hvdWxkLmNvbnRhaW5FcWwoaW5uZXIzKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2luZ2xlLXRva2VuIG11bHRpY2FsbCBzaG91bGQgY29udGFpbiBpdHMgaW5uZXIgY2FsbCBidXQgbm90IG90aGVycycsICgpID0+IHtcbiAgICAgICAgY29uc3QgaW5uZXIxID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKS5zbGljZSgyKTtcbiAgICAgICAgY29uc3QgaW5uZXIyID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTU18yLCBFWFBJUlkpLnNsaWNlKDIpO1xuXG4gICAgICAgIGNvbnN0IHNpbmdsZSA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFtUT0tFTl9BRERSRVNTXSwgRVhQSVJZKTtcblxuICAgICAgICBzaW5nbGUuc2hvdWxkLmNvbnRhaW5FcWwoaW5uZXIxKTtcbiAgICAgICAgc2luZ2xlLnNob3VsZC5ub3QuY29udGFpbkVxbChpbm5lcjIpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdlYWNoIGlubmVyIGNhbGwgc2hvdWxkIHN0YXJ0IHdpdGggZGVsZWdhdGVGb3JVc2VyRGVjcnlwdGlvbiBzZWxlY3RvcicsICgpID0+IHtcbiAgICAgICAgY29uc3QgdG9rZW5zID0gW1RPS0VOX0FERFJFU1MsIFRPS0VOX0FERFJFU1NfMiwgVE9LRU5fQUREUkVTU18zXTtcbiAgICAgICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCB0b2tlbnMsIEVYUElSWSk7XG5cbiAgICAgICAgZm9yIChjb25zdCB0b2tlbiBvZiB0b2tlbnMpIHtcbiAgICAgICAgICBjb25zdCBleHBlY3RlZElubmVyID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgdG9rZW4sIEVYUElSWSkuc2xpY2UoMik7XG4gICAgICAgICAgLy8gRWFjaCBpbm5lciBjYWxsIHN0YXJ0cyB3aXRoIGRlbGVnYXRlRm9yVXNlckRlY3J5cHRpb24gc2VsZWN0b3JcbiAgICAgICAgICBleHBlY3RlZElubmVyLnNob3VsZC5zdGFydFdpdGgoZGVsZWdhdGVGb3JVc2VyRGVjcnlwdGlvbk1ldGhvZElkLnNsaWNlKDIpKTtcbiAgICAgICAgICBjYWxsZGF0YS5zaG91bGQuY29udGFpbkVxbChleHBlY3RlZElubmVyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGl0KCdkaWZmZXJlbnQgZXhwaXJ5IHRpbWVzdGFtcHMgY2hhbmdlIGFsbCBpbm5lciBjYWxscycsICgpID0+IHtcbiAgICAgICAgY29uc3QgYzEgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbVE9LRU5fQUREUkVTUywgVE9LRU5fQUREUkVTU18yXSwgRVhQSVJZKTtcbiAgICAgICAgY29uc3QgYzIgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbVE9LRU5fQUREUkVTUywgVE9LRU5fQUREUkVTU18yXSwgRVhQSVJZICsgODY0MDApO1xuXG4gICAgICAgIC8vIElubmVyIGNhbGxzIHdpdGggb2xkIGV4cGlyeSBzaG91bGQgTk9UIGFwcGVhciBpbiB0aGUgbmV3IG11bHRpY2FsbFxuICAgICAgICBjb25zdCBpbm5lcjFPbGQgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpLnNsaWNlKDIpO1xuICAgICAgICBjMi5zaG91bGQubm90LmNvbnRhaW5FcWwoaW5uZXIxT2xkKTtcblxuICAgICAgICAvLyBBbmQgdmljZSB2ZXJzYVxuICAgICAgICBjb25zdCBpbm5lcjFOZXcgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkgKyA4NjQwMCkuc2xpY2UoMik7XG4gICAgICAgIGMxLnNob3VsZC5ub3QuY29udGFpbkVxbChpbm5lcjFOZXcpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcHJvZHVjZSBsb25nZXIgY2FsbGRhdGEgZm9yIG1vcmUgdG9rZW5zJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBzaW5nbGUgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbVE9LRU5fQUREUkVTU10sIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IGRvdWJsZSA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFtUT0tFTl9BRERSRVNTLCBUT0tFTl9BRERSRVNTXzJdLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCB0cmlwbGUgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShcbiAgICAgICAgICBERUxFR0FURV9BRERSRVNTLFxuICAgICAgICAgIFtUT0tFTl9BRERSRVNTLCBUT0tFTl9BRERSRVNTXzIsIFRPS0VOX0FERFJFU1NfM10sXG4gICAgICAgICAgRVhQSVJZXG4gICAgICAgICk7XG4gICAgICAgIGRvdWJsZS5sZW5ndGguc2hvdWxkLmJlLmdyZWF0ZXJUaGFuKHNpbmdsZS5sZW5ndGgpO1xuICAgICAgICB0cmlwbGUubGVuZ3RoLnNob3VsZC5iZS5ncmVhdGVyVGhhbihkb3VibGUubGVuZ3RoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnZGlmZmVyZW50IHRva2VuIG9yZGVyaW5ncyBzaG91bGQgcHJvZHVjZSBkaWZmZXJlbnQgY2FsbGRhdGEnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGMxID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgW1RPS0VOX0FERFJFU1MsIFRPS0VOX0FERFJFU1NfMl0sIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IGMyID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgW1RPS0VOX0FERFJFU1NfMiwgVE9LRU5fQUREUkVTU10sIEVYUElSWSk7XG4gICAgICAgIGMxLnNob3VsZC5ub3QuZXF1YWwoYzIpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnZXJyb3IgaGFuZGxpbmcnLCAoKSA9PiB7XG4gICAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gZ2l2ZW4gYW4gZW1wdHkgdG9rZW4gYXJyYXknLCAoKSA9PiB7XG4gICAgICAgIHNob3VsZC50aHJvd3MoXG4gICAgICAgICAgKCkgPT4gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgW10sIEVYUElSWSksXG4gICAgICAgICAgL3Rva2VuQ29udHJhY3RBZGRyZXNzZXMgbXVzdCBub3QgYmUgZW1wdHkvXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICBkZXNjcmliZSgnd3JhcEluQ2FsbEZyb21QYXJlbnQnLCAoKSA9PiB7XG4gICAgZGVzY3JpYmUoJ291dHB1dCBmb3JtYXQnLCAoKSA9PiB7XG4gICAgICBpdCgnc2hvdWxkIHByb2R1Y2UgYSAweC1wcmVmaXhlZCBoZXggc3RyaW5nJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBpbm5lciA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IHdyYXBwZWQgPSB3cmFwSW5DYWxsRnJvbVBhcmVudChBQ0xfQUREUkVTUywgaW5uZXIpO1xuICAgICAgICB3cmFwcGVkLnNob3VsZC5iZS5hLlN0cmluZygpO1xuICAgICAgICB3cmFwcGVkLnNob3VsZC5zdGFydFdpdGgoJzB4Jyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBzdGFydCB3aXRoIGNhbGxGcm9tUGFyZW50IHNlbGVjdG9yJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBpbm5lciA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IHdyYXBwZWQgPSB3cmFwSW5DYWxsRnJvbVBhcmVudChBQ0xfQUREUkVTUywgaW5uZXIpO1xuICAgICAgICB3cmFwcGVkLnNsaWNlKDAsIDEwKS5zaG91bGQuZXF1YWwoY2FsbEZyb21QYXJlbnRNZXRob2RJZCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGxvbmdlciBjYWxsZGF0YSB0aGFuIHRoZSBpbm5lciBjYWxsZGF0YScsICgpID0+IHtcbiAgICAgICAgY29uc3QgaW5uZXIgPSBidWlsZERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBUT0tFTl9BRERSRVNTLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCB3cmFwcGVkID0gd3JhcEluQ2FsbEZyb21QYXJlbnQoRk9SV0FSREVSX0FERFJFU1MsIGlubmVyKTtcbiAgICAgICAgd3JhcHBlZC5sZW5ndGguc2hvdWxkLmJlLmdyZWF0ZXJUaGFuKGlubmVyLmxlbmd0aCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdBQkkgcGFyYW1ldGVyIGRlY29kaW5nJywgKCkgPT4ge1xuICAgICAgaXQoJ3Nob3VsZCBkZWNvZGUgdGFyZ2V0IGFkZHJlc3MgY29ycmVjdGx5JywgKCkgPT4ge1xuICAgICAgICBjb25zdCBpbm5lciA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IHdyYXBwZWQgPSB3cmFwSW5DYWxsRnJvbVBhcmVudChBQ0xfQUREUkVTUywgaW5uZXIpO1xuICAgICAgICBjb25zdCBwYXlsb2FkID0gQnVmZmVyLmZyb20od3JhcHBlZC5zbGljZSgxMCksICdoZXgnKTtcbiAgICAgICAgY29uc3QgW3RhcmdldF0gPSBFdGhlcmV1bUFiaS5yYXdEZWNvZGUoWydhZGRyZXNzJywgJ3VpbnQyNTYnLCAnYnl0ZXMnXSwgcGF5bG9hZCk7XG4gICAgICAgICh0YXJnZXQgYXMgQnVmZmVyKS50b1N0cmluZygnaGV4Jykuc2hvdWxkLmVxdWFsKEFDTF9BRERSRVNTLnNsaWNlKDIpLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgZW5jb2RlIHZhbHVlIGFzIDAgKG5vIEVUSCB0cmFuc2ZlciknLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGlubmVyID0gYnVpbGREZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgVE9LRU5fQUREUkVTUywgRVhQSVJZKTtcbiAgICAgICAgY29uc3Qgd3JhcHBlZCA9IHdyYXBJbkNhbGxGcm9tUGFyZW50KEFDTF9BRERSRVNTLCBpbm5lcik7XG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSBCdWZmZXIuZnJvbSh3cmFwcGVkLnNsaWNlKDEwKSwgJ2hleCcpO1xuICAgICAgICBjb25zdCBbLCB2YWx1ZV0gPSBFdGhlcmV1bUFiaS5yYXdEZWNvZGUoWydhZGRyZXNzJywgJ3VpbnQyNTYnLCAnYnl0ZXMnXSwgcGF5bG9hZCk7XG4gICAgICAgIHZhbHVlLnRvU3RyaW5nKCkuc2hvdWxkLmVxdWFsKCcwJyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBwcmVzZXJ2ZSBpbm5lciBjYWxsZGF0YSBleGFjdGx5JywgKCkgPT4ge1xuICAgICAgICBjb25zdCBpbm5lciA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IHdyYXBwZWQgPSB3cmFwSW5DYWxsRnJvbVBhcmVudChBQ0xfQUREUkVTUywgaW5uZXIpO1xuICAgICAgICBjb25zdCBwYXlsb2FkID0gQnVmZmVyLmZyb20od3JhcHBlZC5zbGljZSgxMCksICdoZXgnKTtcbiAgICAgICAgY29uc3QgWywgLCBkYXRhXSA9IEV0aGVyZXVtQWJpLnJhd0RlY29kZShbJ2FkZHJlc3MnLCAndWludDI1NicsICdieXRlcyddLCBwYXlsb2FkKTtcbiAgICAgICAgKCcweCcgKyAoZGF0YSBhcyBCdWZmZXIpLnRvU3RyaW5nKCdoZXgnKSkuc2hvdWxkLmVxdWFsKGlubmVyKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHByZXNlcnZlIG11bHRpY2FsbCBpbm5lciBjYWxsZGF0YSBleGFjdGx5JywgKCkgPT4ge1xuICAgICAgICBjb25zdCBpbm5lciA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFtUT0tFTl9BRERSRVNTLCBUT0tFTl9BRERSRVNTXzJdLCBFWFBJUlkpO1xuICAgICAgICBjb25zdCB3cmFwcGVkID0gd3JhcEluQ2FsbEZyb21QYXJlbnQoQUNMX0FERFJFU1MsIGlubmVyKTtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IEJ1ZmZlci5mcm9tKHdyYXBwZWQuc2xpY2UoMTApLCAnaGV4Jyk7XG4gICAgICAgIGNvbnN0IFssICwgZGF0YV0gPSBFdGhlcmV1bUFiaS5yYXdEZWNvZGUoWydhZGRyZXNzJywgJ3VpbnQyNTYnLCAnYnl0ZXMnXSwgcGF5bG9hZCk7XG4gICAgICAgICgnMHgnICsgKGRhdGEgYXMgQnVmZmVyKS50b1N0cmluZygnaGV4JykpLnNob3VsZC5lcXVhbChpbm5lcik7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCd0YXJnZXQgYWRkcmVzcyBpc29sYXRpb24nLCAoKSA9PiB7XG4gICAgICBpdCgnZGlmZmVyZW50IHRhcmdldCBhZGRyZXNzZXMgc2hvdWxkIHByb2R1Y2UgZGlmZmVyZW50IGNhbGxkYXRhJywgKCkgPT4ge1xuICAgICAgICBjb25zdCBpbm5lciA9IGJ1aWxkRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIFRPS0VOX0FERFJFU1MsIEVYUElSWSk7XG4gICAgICAgIGNvbnN0IHcxID0gd3JhcEluQ2FsbEZyb21QYXJlbnQoQUNMX0FERFJFU1MsIGlubmVyKTtcbiAgICAgICAgY29uc3QgdzIgPSB3cmFwSW5DYWxsRnJvbVBhcmVudChGT1JXQVJERVJfQUREUkVTUywgaW5uZXIpO1xuICAgICAgICB3MS5zaG91bGQubm90LmVxdWFsKHcyKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|