@bitgo-beta/sdk-coin-sui 3.0.3-beta.182 → 3.0.3-beta.1821
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/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -2
- package/dist/src/lib/compareTransactionBlocks.js +2 -3
- package/dist/src/lib/constants.d.ts +9 -2
- package/dist/src/lib/constants.d.ts.map +1 -1
- package/dist/src/lib/constants.js +18 -2
- package/dist/src/lib/customTransaction.js +3 -3
- package/dist/src/lib/customTransactionBuilder.js +5 -5
- package/dist/src/lib/iface.d.ts +80 -12
- package/dist/src/lib/iface.d.ts.map +1 -1
- package/dist/src/lib/iface.js +34 -5
- package/dist/src/lib/index.d.ts +6 -0
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +36 -10
- package/dist/src/lib/keyPair.js +24 -10
- package/dist/src/lib/mystenlab/builder/Inputs.d.ts +64 -11
- package/dist/src/lib/mystenlab/builder/Inputs.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/builder/Inputs.js +63 -19
- package/dist/src/lib/mystenlab/builder/TransactionBlock.d.ts +88 -355
- package/dist/src/lib/mystenlab/builder/TransactionBlock.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/builder/TransactionBlock.js +44 -25
- package/dist/src/lib/mystenlab/builder/TransactionDataBlock.d.ts +152 -77
- package/dist/src/lib/mystenlab/builder/TransactionDataBlock.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/builder/TransactionDataBlock.js +54 -44
- package/dist/src/lib/mystenlab/builder/Transactions.d.ts +133 -188
- package/dist/src/lib/mystenlab/builder/Transactions.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/builder/Transactions.js +52 -53
- package/dist/src/lib/mystenlab/builder/bcs.d.ts +1 -1
- package/dist/src/lib/mystenlab/builder/bcs.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/builder/bcs.js +2 -2
- package/dist/src/lib/mystenlab/builder/index.js +6 -2
- package/dist/src/lib/mystenlab/builder/serializer.js +6 -8
- package/dist/src/lib/mystenlab/builder/utils.d.ts +1 -1
- package/dist/src/lib/mystenlab/builder/utils.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/builder/utils.js +4 -4
- package/dist/src/lib/mystenlab/cryptography/hash.js +3 -4
- package/dist/src/lib/mystenlab/framework/framework.d.ts +6 -6
- package/dist/src/lib/mystenlab/framework/framework.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/framework/framework.js +22 -25
- package/dist/src/lib/mystenlab/framework/index.js +6 -2
- package/dist/src/lib/mystenlab/framework/sui-system-state.js +2 -2
- package/dist/src/lib/mystenlab/txn-data-serializers/type-tag-serializer.js +2 -2
- package/dist/src/lib/mystenlab/types/coin.d.ts +13 -11
- package/dist/src/lib/mystenlab/types/coin.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/types/coin.js +20 -19
- package/dist/src/lib/mystenlab/types/common.d.ts +8 -8
- package/dist/src/lib/mystenlab/types/common.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/types/common.js +22 -22
- package/dist/src/lib/mystenlab/types/events.d.ts +15 -15
- package/dist/src/lib/mystenlab/types/events.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/types/events.js +17 -17
- package/dist/src/lib/mystenlab/types/index.js +6 -2
- package/dist/src/lib/mystenlab/types/normalized.d.ts +21 -21
- package/dist/src/lib/mystenlab/types/normalized.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/types/normalized.js +41 -41
- package/dist/src/lib/mystenlab/types/objects.d.ts +51 -51
- package/dist/src/lib/mystenlab/types/objects.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/types/objects.js +96 -106
- package/dist/src/lib/mystenlab/types/option.d.ts +1 -1
- package/dist/src/lib/mystenlab/types/option.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/types/option.js +2 -3
- package/dist/src/lib/mystenlab/types/sui-bcs.d.ts +55 -29
- package/dist/src/lib/mystenlab/types/sui-bcs.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/types/sui-bcs.js +29 -5
- package/dist/src/lib/mystenlab/types/transactions.d.ts +625 -625
- package/dist/src/lib/mystenlab/types/transactions.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/types/transactions.js +178 -194
- package/dist/src/lib/mystenlab/types/validator.d.ts +13 -13
- package/dist/src/lib/mystenlab/types/validator.d.ts.map +1 -1
- package/dist/src/lib/mystenlab/types/validator.js +124 -124
- package/dist/src/lib/resources/walrusConfig.d.ts +22 -0
- package/dist/src/lib/resources/walrusConfig.d.ts.map +1 -0
- package/dist/src/lib/resources/walrusConfig.js +37 -0
- package/dist/src/lib/rpcClient.d.ts +5 -0
- package/dist/src/lib/rpcClient.d.ts.map +1 -0
- package/dist/src/lib/rpcClient.js +74 -0
- package/dist/src/lib/stakingBuilder.d.ts.map +1 -1
- package/dist/src/lib/stakingBuilder.js +23 -7
- package/dist/src/lib/stakingTransaction.d.ts +0 -1
- package/dist/src/lib/stakingTransaction.d.ts.map +1 -1
- package/dist/src/lib/stakingTransaction.js +26 -15
- package/dist/src/lib/tokenTransferBuilder.d.ts +66 -0
- package/dist/src/lib/tokenTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/tokenTransferBuilder.js +202 -0
- package/dist/src/lib/tokenTransferTransaction.d.ts +59 -0
- package/dist/src/lib/tokenTransferTransaction.d.ts.map +1 -0
- package/dist/src/lib/tokenTransferTransaction.js +272 -0
- package/dist/src/lib/transaction.d.ts +21 -4
- package/dist/src/lib/transaction.d.ts.map +1 -1
- package/dist/src/lib/transaction.js +129 -17
- package/dist/src/lib/transactionBuilder.d.ts +13 -4
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
- package/dist/src/lib/transactionBuilder.js +34 -4
- package/dist/src/lib/transactionBuilderFactory.d.ts +11 -2
- package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -1
- package/dist/src/lib/transactionBuilderFactory.js +32 -1
- package/dist/src/lib/transferBuilder.d.ts +58 -1
- package/dist/src/lib/transferBuilder.d.ts.map +1 -1
- package/dist/src/lib/transferBuilder.js +310 -24
- package/dist/src/lib/transferTransaction.d.ts +6 -1
- package/dist/src/lib/transferTransaction.d.ts.map +1 -1
- package/dist/src/lib/transferTransaction.js +129 -12
- package/dist/src/lib/unstakingBuilder.js +6 -6
- package/dist/src/lib/unstakingTransaction.d.ts +0 -1
- package/dist/src/lib/unstakingTransaction.d.ts.map +1 -1
- package/dist/src/lib/unstakingTransaction.js +31 -17
- package/dist/src/lib/utils.d.ts +24 -3
- package/dist/src/lib/utils.d.ts.map +1 -1
- package/dist/src/lib/utils.js +254 -21
- package/dist/src/lib/walrusStakingBuilder.d.ts +66 -0
- package/dist/src/lib/walrusStakingBuilder.d.ts.map +1 -0
- package/dist/src/lib/walrusStakingBuilder.js +200 -0
- package/dist/src/lib/walrusStakingTransaction.d.ts +52 -0
- package/dist/src/lib/walrusStakingTransaction.d.ts.map +1 -0
- package/dist/src/lib/walrusStakingTransaction.js +269 -0
- package/dist/src/lib/walrusWithdrawStakeBuilder.d.ts +36 -0
- package/dist/src/lib/walrusWithdrawStakeBuilder.d.ts.map +1 -0
- package/dist/src/lib/walrusWithdrawStakeBuilder.js +173 -0
- package/dist/src/lib/walrusWithdrawStakeTransaction.d.ts +21 -0
- package/dist/src/lib/walrusWithdrawStakeTransaction.d.ts.map +1 -0
- package/dist/src/lib/walrusWithdrawStakeTransaction.js +190 -0
- package/dist/src/register.d.ts.map +1 -1
- package/dist/src/register.js +5 -1
- package/dist/src/sui.d.ts +46 -8
- package/dist/src/sui.d.ts.map +1 -1
- package/dist/src/sui.js +525 -37
- package/dist/src/suiToken.d.ts +22 -0
- package/dist/src/suiToken.d.ts.map +1 -0
- package/dist/src/suiToken.js +61 -0
- package/dist/src/tsui.js +1 -1
- package/dist/test/integration/index.d.ts +1 -0
- package/dist/test/integration/index.d.ts.map +1 -0
- package/dist/test/integration/index.js +1 -0
- package/dist/test/local_fullnode/RpcClient.d.ts +60 -0
- package/dist/test/local_fullnode/RpcClient.d.ts.map +1 -0
- package/dist/test/local_fullnode/RpcClient.js +111 -0
- package/dist/test/local_fullnode/faucet.d.ts +6 -0
- package/dist/test/local_fullnode/faucet.d.ts.map +1 -0
- package/dist/test/local_fullnode/faucet.js +17 -0
- package/dist/test/local_fullnode/transactions.d.ts +2 -0
- package/dist/test/local_fullnode/transactions.d.ts.map +1 -0
- package/dist/test/local_fullnode/transactions.js +190 -0
- package/dist/test/resources/sui.d.ts +458 -0
- package/dist/test/resources/sui.d.ts.map +1 -0
- package/dist/test/resources/sui.js +632 -0
- package/dist/test/unit/compareTransactionBlocks.d.ts +2 -0
- package/dist/test/unit/compareTransactionBlocks.d.ts.map +1 -0
- package/dist/test/unit/compareTransactionBlocks.js +64 -0
- package/dist/test/unit/getBuilderFactory.d.ts +3 -0
- package/dist/test/unit/getBuilderFactory.d.ts.map +1 -0
- package/dist/test/unit/getBuilderFactory.js +10 -0
- package/dist/test/unit/keyPair.d.ts +2 -0
- package/dist/test/unit/keyPair.d.ts.map +1 -0
- package/dist/test/unit/keyPair.js +72 -0
- package/dist/test/unit/sui.d.ts +2 -0
- package/dist/test/unit/sui.d.ts.map +1 -0
- package/dist/test/unit/sui.js +2423 -0
- package/dist/test/unit/suiToken.d.ts +2 -0
- package/dist/test/unit/suiToken.d.ts.map +1 -0
- package/dist/test/unit/suiToken.js +39 -0
- package/dist/test/unit/transactionBuilder/customTransactionBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/customTransactionBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/customTransactionBuilder.js +106 -0
- package/dist/test/unit/transactionBuilder/stakingBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/stakingBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/stakingBuilder.js +152 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/tokenTransferBuilder.js +255 -0
- package/dist/test/unit/transactionBuilder/transactionBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/transactionBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/transactionBuilder.js +639 -0
- package/dist/test/unit/transactionBuilder/transferBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/transferBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/transferBuilder.js +1055 -0
- package/dist/test/unit/transactionBuilder/unstakingBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/unstakingBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/unstakingBuilder.js +115 -0
- package/dist/test/unit/transactionBuilder/walrusStakingBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/walrusStakingBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/walrusStakingBuilder.js +162 -0
- package/dist/test/unit/transactionBuilder/walrusWithdrawBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/walrusWithdrawBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/walrusWithdrawBuilder.js +181 -0
- package/dist/test/unit/transferTransaction.d.ts +2 -0
- package/dist/test/unit/transferTransaction.d.ts.map +1 -0
- package/dist/test/unit/transferTransaction.js +94 -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 +186 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +16 -12
- package/.eslintignore +0 -6
- package/.mocharc.yml +0 -7
- package/CHANGELOG.md +0 -420
|
@@ -0,0 +1,1055 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const assert_1 = __importDefault(require("assert"));
|
|
40
|
+
const getBuilderFactory_1 = require("../getBuilderFactory");
|
|
41
|
+
const testData = __importStar(require("../../resources/sui"));
|
|
42
|
+
const should_1 = __importDefault(require("should"));
|
|
43
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
44
|
+
const utils_1 = __importDefault(require("../../../src/lib/utils"));
|
|
45
|
+
const transaction_1 = require("../../../src/lib/transaction");
|
|
46
|
+
const iface_1 = require("../../../src/lib/iface");
|
|
47
|
+
const constants_1 = require("../../../src/lib/constants");
|
|
48
|
+
describe('Sui Transfer Builder', () => {
|
|
49
|
+
const factory = (0, getBuilderFactory_1.getBuilderFactory)('tsui');
|
|
50
|
+
describe('Succeed', () => {
|
|
51
|
+
it('should build a transfer tx', async function () {
|
|
52
|
+
const txBuilder = factory.getTransferBuilder();
|
|
53
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
54
|
+
txBuilder.sender(testData.sender.address);
|
|
55
|
+
txBuilder.send(testData.recipients);
|
|
56
|
+
txBuilder.gasData(testData.gasData);
|
|
57
|
+
const tx = await txBuilder.build();
|
|
58
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
59
|
+
tx.suiTransaction.gasData.payment.should.deepEqual(testData.coinsGasPayment);
|
|
60
|
+
tx.inputs.length.should.equal(1);
|
|
61
|
+
tx.inputs[0].should.deepEqual({
|
|
62
|
+
address: testData.sender.address,
|
|
63
|
+
value: (testData.AMOUNT * 2).toString(),
|
|
64
|
+
coin: 'tsui',
|
|
65
|
+
});
|
|
66
|
+
tx.outputs.length.should.equal(2);
|
|
67
|
+
tx.outputs[0].should.deepEqual({
|
|
68
|
+
address: testData.recipients[0].address,
|
|
69
|
+
value: testData.recipients[0].amount,
|
|
70
|
+
coin: 'tsui',
|
|
71
|
+
});
|
|
72
|
+
tx.outputs[1].should.deepEqual({
|
|
73
|
+
address: testData.recipients[1].address,
|
|
74
|
+
value: testData.recipients[1].amount,
|
|
75
|
+
coin: 'tsui',
|
|
76
|
+
});
|
|
77
|
+
const rawTx = tx.toBroadcastFormat();
|
|
78
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
79
|
+
should_1.default.equal(rawTx, testData.TRANSFER);
|
|
80
|
+
});
|
|
81
|
+
it('should build a sponsored transfer tx with inputObjects', async function () {
|
|
82
|
+
const inputObjects = [
|
|
83
|
+
{
|
|
84
|
+
objectId: '0000000000000000000000001234567890abcdef1234567890abcdef12345678',
|
|
85
|
+
version: 100,
|
|
86
|
+
digest: '2B8XKQJ7mfxQPUWqJJAGjzBAzivkWKq2cEa3W8LLz1yB',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
objectId: '000000000000000000000000abcdef1234567890abcdef1234567890abcdef12',
|
|
90
|
+
version: 200,
|
|
91
|
+
digest: 'DoJwXuz9oU5Y5v5vBRiTgisVTQuZQLmHZWeqJzzD5QUE',
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
// Create gas data with different owner (sponsor)
|
|
95
|
+
const sponsoredGasData = {
|
|
96
|
+
...testData.gasData,
|
|
97
|
+
owner: testData.feePayer.address, // Different from sender
|
|
98
|
+
};
|
|
99
|
+
const txBuilder = factory.getTransferBuilder();
|
|
100
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
101
|
+
txBuilder.sender(testData.sender.address); // Sender
|
|
102
|
+
txBuilder.send(testData.recipients);
|
|
103
|
+
txBuilder.gasData(sponsoredGasData); // Gas paid by sponsor
|
|
104
|
+
txBuilder.inputObjects(inputObjects); // Required for sponsored tx
|
|
105
|
+
const tx = await txBuilder.build();
|
|
106
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
107
|
+
const suiTx = tx;
|
|
108
|
+
// Verify transaction structure for sponsored transaction
|
|
109
|
+
const programmableTx = suiTx.suiTransaction.tx;
|
|
110
|
+
programmableTx.transactions.length.should.be.greaterThan(0);
|
|
111
|
+
// Verify sponsored transaction characteristics
|
|
112
|
+
suiTx.suiTransaction.sender.should.equal(testData.sender.address);
|
|
113
|
+
suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
|
|
114
|
+
// Should have transactions for merging/splitting and transferring when using inputObjects
|
|
115
|
+
programmableTx.transactions.length.should.be.greaterThan(0);
|
|
116
|
+
// Verify we have transfer operations (the exact structure varies with API versions)
|
|
117
|
+
should_1.default.exist(programmableTx.transactions);
|
|
118
|
+
// Verify inputObjects are not used in gas payment (they're separate)
|
|
119
|
+
suiTx.suiTransaction.gasData.payment.should.not.containDeep(inputObjects);
|
|
120
|
+
const rawTx = tx.toBroadcastFormat();
|
|
121
|
+
should_1.default.exist(rawTx);
|
|
122
|
+
should_1.default.equal(typeof rawTx, 'string');
|
|
123
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
124
|
+
});
|
|
125
|
+
it('should build a split coin tx', async function () {
|
|
126
|
+
const txBuilder = factory.getTransferBuilder();
|
|
127
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
128
|
+
txBuilder.sender(testData.sender.address);
|
|
129
|
+
const amount = 1000000000;
|
|
130
|
+
const recipients = new Array(100).fill({ address: testData.sender.address, amount: amount.toString() });
|
|
131
|
+
txBuilder.send(recipients);
|
|
132
|
+
txBuilder.gasData(testData.gasData);
|
|
133
|
+
const tx = await txBuilder.build();
|
|
134
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
135
|
+
tx.suiTransaction.gasData.payment.should.deepEqual(testData.coinsGasPayment);
|
|
136
|
+
tx.inputs.length.should.equal(1);
|
|
137
|
+
tx.inputs[0].should.deepEqual({
|
|
138
|
+
address: testData.sender.address,
|
|
139
|
+
value: (amount * 100).toString(),
|
|
140
|
+
coin: 'tsui',
|
|
141
|
+
});
|
|
142
|
+
tx.outputs.length.should.equal(100);
|
|
143
|
+
tx.outputs.forEach((output) => output.should.deepEqual({
|
|
144
|
+
address: testData.sender.address,
|
|
145
|
+
value: amount.toString(),
|
|
146
|
+
coin: 'tsui',
|
|
147
|
+
}));
|
|
148
|
+
});
|
|
149
|
+
it('should build a split coin tx with more than 255 input objects', async function () {
|
|
150
|
+
const amount = 1000000000;
|
|
151
|
+
const numberOfRecipients = 10;
|
|
152
|
+
const numberOfPaymentObjects = 1000;
|
|
153
|
+
const txBuilder = factory.getTransferBuilder();
|
|
154
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
155
|
+
txBuilder.sender(testData.sender.address);
|
|
156
|
+
const recipients = new Array(numberOfRecipients).fill({
|
|
157
|
+
address: testData.sender.address,
|
|
158
|
+
amount: amount.toString(),
|
|
159
|
+
});
|
|
160
|
+
const gasData = {
|
|
161
|
+
...testData.gasData,
|
|
162
|
+
payment: testData.generateObjects(numberOfPaymentObjects),
|
|
163
|
+
};
|
|
164
|
+
txBuilder.send(recipients);
|
|
165
|
+
txBuilder.gasData(gasData);
|
|
166
|
+
const tx = await txBuilder.build();
|
|
167
|
+
(0, assert_1.default)(tx instanceof transaction_1.Transaction);
|
|
168
|
+
tx.type.should.equal(sdk_core_1.TransactionType.Send);
|
|
169
|
+
tx.inputs.length.should.equal(1);
|
|
170
|
+
tx.inputs[0].should.deepEqual({
|
|
171
|
+
address: testData.sender.address,
|
|
172
|
+
value: (amount * 10).toString(),
|
|
173
|
+
coin: 'tsui',
|
|
174
|
+
});
|
|
175
|
+
tx.outputs.length.should.equal(10);
|
|
176
|
+
tx.outputs.forEach((output) => output.should.deepEqual({
|
|
177
|
+
coin: 'tsui',
|
|
178
|
+
address: testData.sender.address,
|
|
179
|
+
value: amount.toString(),
|
|
180
|
+
}));
|
|
181
|
+
tx.suiTransaction.gasData.owner.should.equal(gasData.owner);
|
|
182
|
+
tx.suiTransaction.gasData.price.should.equal(gasData.price);
|
|
183
|
+
tx.suiTransaction.gasData.budget.should.equal(gasData.budget);
|
|
184
|
+
tx.suiTransaction.gasData.payment.length.should.equal(constants_1.MAX_GAS_OBJECTS - 1);
|
|
185
|
+
const programmableTx = tx.suiTransaction.tx;
|
|
186
|
+
// total objects - objects sent as gas payment + no. of recipient amounts(pure)
|
|
187
|
+
// + no. of unique recipient addresses(de-duped objects)
|
|
188
|
+
programmableTx.inputs.length.should.equal(numberOfPaymentObjects - (constants_1.MAX_GAS_OBJECTS - 1) + numberOfRecipients + 1);
|
|
189
|
+
programmableTx.transactions[0].kind.should.equal('MergeCoins');
|
|
190
|
+
programmableTx.transactions[0].sources.length.should.equal(constants_1.MAX_COMMAND_ARGS - 1);
|
|
191
|
+
programmableTx.transactions[1].kind.should.equal('MergeCoins');
|
|
192
|
+
programmableTx.transactions[1].sources.length.should.equal(numberOfPaymentObjects - (constants_1.MAX_COMMAND_ARGS - 1) - (constants_1.MAX_GAS_OBJECTS - 1));
|
|
193
|
+
const rawTx = tx.toBroadcastFormat();
|
|
194
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
195
|
+
const rebuilder = factory.from(rawTx);
|
|
196
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
197
|
+
const rebuiltTx = await rebuilder.build();
|
|
198
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
199
|
+
rebuiltTx.toJson().gasData.payment.length.should.equal(numberOfPaymentObjects);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
describe('Fail', () => {
|
|
203
|
+
it('should fail for invalid sender', async function () {
|
|
204
|
+
const builder = factory.getTransferBuilder();
|
|
205
|
+
(0, should_1.default)(() => builder.sender('randomString')).throwError('Invalid or missing sender, got: randomString');
|
|
206
|
+
});
|
|
207
|
+
it('should fail for invalid payTx', async function () {
|
|
208
|
+
const builder = factory.getTransferBuilder();
|
|
209
|
+
(0, should_1.default)(() => builder.send([testData.invalidRecipients[0]])).throwError('Invalid or missing address, got: randomString');
|
|
210
|
+
(0, should_1.default)(() => builder.send([testData.invalidRecipients[1]])).throwError('Invalid recipient amount');
|
|
211
|
+
});
|
|
212
|
+
it('should fail for invalid gasData', function () {
|
|
213
|
+
const builder = factory.getTransferBuilder();
|
|
214
|
+
(0, should_1.default)(() => builder.gasData(testData.invalidGasOwner)).throwError(`Invalid gas address ${testData.invalidGasOwner.owner}`);
|
|
215
|
+
});
|
|
216
|
+
it('should fail for invalid gasBudget', function () {
|
|
217
|
+
const builder = factory.getTransferBuilder();
|
|
218
|
+
(0, should_1.default)(() => builder.gasData(testData.invalidGasBudget)).throwError('Invalid gas budget -1');
|
|
219
|
+
});
|
|
220
|
+
it('should fail for invalid gasPayment', function () {
|
|
221
|
+
const builder = factory.getTransferBuilder();
|
|
222
|
+
const invalidGasPayment = {
|
|
223
|
+
...testData.gasDataWithoutGasPayment,
|
|
224
|
+
payment: [
|
|
225
|
+
{
|
|
226
|
+
objectId: '',
|
|
227
|
+
version: -1,
|
|
228
|
+
digest: '',
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
};
|
|
232
|
+
(0, should_1.default)(() => builder.gasData(invalidGasPayment)).throwError('Invalid payment, invalid or missing version');
|
|
233
|
+
});
|
|
234
|
+
it('should fail for invalid inputObjects', function () {
|
|
235
|
+
const builder = factory.getTransferBuilder();
|
|
236
|
+
const invalidInputObjects = [
|
|
237
|
+
{
|
|
238
|
+
objectId: '',
|
|
239
|
+
version: -1,
|
|
240
|
+
digest: '',
|
|
241
|
+
},
|
|
242
|
+
];
|
|
243
|
+
(0, should_1.default)(() => builder.inputObjects(invalidInputObjects)).throwError('Invalid input object, invalid or missing version');
|
|
244
|
+
});
|
|
245
|
+
it('should build transfer with different gas owner but no inputObjects', async function () {
|
|
246
|
+
const sponsoredGasData = {
|
|
247
|
+
...testData.gasData,
|
|
248
|
+
owner: testData.feePayer.address, // Different from sender
|
|
249
|
+
};
|
|
250
|
+
const txBuilder = factory.getTransferBuilder();
|
|
251
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
252
|
+
txBuilder.sender(testData.sender.address); // Sender
|
|
253
|
+
txBuilder.send(testData.recipients);
|
|
254
|
+
txBuilder.gasData(sponsoredGasData); // Gas paid by sponsor
|
|
255
|
+
// Note: NOT providing inputObjects - should still work (fee sponsorship without coin sponsorship)
|
|
256
|
+
const tx = await txBuilder.build();
|
|
257
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
258
|
+
const suiTx = tx;
|
|
259
|
+
should_1.default.not.exist(suiTx.suiTransaction.inputObjects);
|
|
260
|
+
const rawTx = tx.toBroadcastFormat();
|
|
261
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
262
|
+
});
|
|
263
|
+
it('should extract inputObjects from transaction data via toJson', async function () {
|
|
264
|
+
const inputObjects = [
|
|
265
|
+
{
|
|
266
|
+
objectId: '0x1234567890abcdef1234567890abcdef12345678',
|
|
267
|
+
version: 100,
|
|
268
|
+
digest: '2B8XKQJ7mfxQPUWqJJAGjzBAzivkWKq2cEa3W8LLz1yB',
|
|
269
|
+
},
|
|
270
|
+
];
|
|
271
|
+
const sponsoredGasData = {
|
|
272
|
+
...testData.gasData,
|
|
273
|
+
owner: testData.feePayer.address, // Different from sender
|
|
274
|
+
};
|
|
275
|
+
const txBuilder = factory.getTransferBuilder();
|
|
276
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
277
|
+
txBuilder.sender(testData.sender.address);
|
|
278
|
+
txBuilder.send(testData.recipients);
|
|
279
|
+
txBuilder.gasData(sponsoredGasData);
|
|
280
|
+
txBuilder.inputObjects(inputObjects);
|
|
281
|
+
const tx = await txBuilder.build();
|
|
282
|
+
// Test that toJson extracts inputObjects from transaction structure
|
|
283
|
+
const txData = tx.toJson();
|
|
284
|
+
should_1.default.exist(txData.inputObjects);
|
|
285
|
+
// The toJson should extract the inputObjects from the transaction structure
|
|
286
|
+
// This tests our new getInputObjectsFromTx method
|
|
287
|
+
should_1.default.exist(txData.inputObjects);
|
|
288
|
+
Array.isArray(txData.inputObjects).should.equal(true);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
describe('fundsInAddressBalance', () => {
|
|
292
|
+
const FUNDS_IN_ADDRESS_BALANCE = '5000000000'; // 5 SUI
|
|
293
|
+
it('should build Path 2b: self-pay, address-balance only — uses withdrawal+redeem_funds, not SplitCoins(GasCoin)', async function () {
|
|
294
|
+
// Regression for production InsufficientCoinBalance failures on consolidation.
|
|
295
|
+
// With payment=[], GasCoin only has gas-budget-worth of balance for PTB operations;
|
|
296
|
+
// SplitCoins(GasCoin, [large_amount]) always fails at command 0.
|
|
297
|
+
// Path 2b must use withdrawal+redeem_funds to materialise the address balance as a
|
|
298
|
+
// coin object and split from that coin instead.
|
|
299
|
+
const gasDataNoPayment = {
|
|
300
|
+
...testData.gasDataWithoutGasPayment,
|
|
301
|
+
payment: [],
|
|
302
|
+
};
|
|
303
|
+
const txBuilder = factory.getTransferBuilder();
|
|
304
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
305
|
+
txBuilder.sender(testData.sender.address);
|
|
306
|
+
txBuilder.send(testData.recipients); // 2 recipients
|
|
307
|
+
txBuilder.gasData(gasDataNoPayment);
|
|
308
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
309
|
+
const tx = await txBuilder.build();
|
|
310
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
311
|
+
const suiTx = tx;
|
|
312
|
+
suiTx.suiTransaction.gasData.payment.length.should.equal(0);
|
|
313
|
+
// Path 2b PTB command sequence (2 recipients):
|
|
314
|
+
// 0: MoveCall(redeem_funds) — materialise addrCoin from address balance
|
|
315
|
+
// 1: SplitCoins(addrCoin, [amount0]) — split for recipient 0
|
|
316
|
+
// 2: TransferObjects — send to recipient 0
|
|
317
|
+
// 3: SplitCoins(addrCoin, [amount1]) — split for recipient 1
|
|
318
|
+
// 4: TransferObjects — send to recipient 1
|
|
319
|
+
// 5: MergeCoins(GasCoin, [addrCoin]) — destroy 0-balance addrCoin; gas from accumulator
|
|
320
|
+
const cmds = suiTx.suiTransaction.tx.transactions;
|
|
321
|
+
cmds[0].kind.should.equal('MoveCall', 'command 0 must be MoveCall(redeem_funds)');
|
|
322
|
+
cmds[0].target.should.equal('0x2::coin::redeem_funds');
|
|
323
|
+
cmds[1].kind.should.equal('SplitCoins', 'command 1 must be SplitCoins(addrCoin)');
|
|
324
|
+
cmds[2].kind.should.equal('TransferObjects', 'command 2 must be TransferObjects');
|
|
325
|
+
cmds[3].kind.should.equal('SplitCoins', 'command 3 must be SplitCoins(addrCoin)');
|
|
326
|
+
cmds[4].kind.should.equal('TransferObjects', 'command 4 must be TransferObjects');
|
|
327
|
+
cmds[5].kind.should.equal('MergeCoins', 'command 5 must be MergeCoins(GasCoin, [addrCoin])');
|
|
328
|
+
cmds.length.should.equal(6);
|
|
329
|
+
suiTx.suiTransaction.fundsInAddressBalance.should.equal(FUNDS_IN_ADDRESS_BALANCE);
|
|
330
|
+
// Transaction parser must correctly identify recipients despite the MoveCall preamble
|
|
331
|
+
const parsedRecipients = utils_1.default.getRecipients(suiTx.suiTransaction);
|
|
332
|
+
parsedRecipients.length.should.equal(testData.recipients.length);
|
|
333
|
+
parsedRecipients[0].address.should.equal(testData.recipients[0].address);
|
|
334
|
+
parsedRecipients[0].amount.should.equal(testData.recipients[0].amount);
|
|
335
|
+
const rawTx = tx.toBroadcastFormat();
|
|
336
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
337
|
+
// Round-trip: rebuilt transaction must be bit-for-bit identical
|
|
338
|
+
const rebuilder = factory.from(rawTx);
|
|
339
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
340
|
+
const rebuiltTx = await rebuilder.build();
|
|
341
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
342
|
+
});
|
|
343
|
+
it('should build Path 2b with a single recipient', async function () {
|
|
344
|
+
const SEND_AMOUNT = '1275170993710'; // realistic consolidation amount (~1275 SUI)
|
|
345
|
+
const ADDR_BAL = '1275177540910'; // fundsInAddressBalance > SEND_AMOUNT + gas budget
|
|
346
|
+
const gasDataNoPayment = {
|
|
347
|
+
...testData.gasDataWithoutGasPayment,
|
|
348
|
+
payment: [],
|
|
349
|
+
};
|
|
350
|
+
const txBuilder = factory.getTransferBuilder();
|
|
351
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
352
|
+
txBuilder.sender(testData.sender.address);
|
|
353
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: SEND_AMOUNT }]);
|
|
354
|
+
txBuilder.gasData(gasDataNoPayment);
|
|
355
|
+
txBuilder.fundsInAddressBalance(ADDR_BAL);
|
|
356
|
+
const tx = await txBuilder.build();
|
|
357
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
358
|
+
const suiTx = tx;
|
|
359
|
+
const cmds = suiTx.suiTransaction.tx.transactions;
|
|
360
|
+
// Command sequence for 1 recipient:
|
|
361
|
+
// 0: MoveCall(redeem_funds)
|
|
362
|
+
// 1: SplitCoins(addrCoin, [SEND_AMOUNT])
|
|
363
|
+
// 2: TransferObjects
|
|
364
|
+
// 3: MergeCoins(GasCoin, [addrCoin])
|
|
365
|
+
cmds[0].kind.should.equal('MoveCall');
|
|
366
|
+
cmds[0].target.should.equal('0x2::coin::redeem_funds');
|
|
367
|
+
cmds[1].kind.should.equal('SplitCoins');
|
|
368
|
+
cmds[2].kind.should.equal('TransferObjects');
|
|
369
|
+
cmds[3].kind.should.equal('MergeCoins', 'expected MergeCoins to consume 0-balance addrCoin');
|
|
370
|
+
cmds.length.should.equal(4);
|
|
371
|
+
const parsedRecipients = utils_1.default.getRecipients(suiTx.suiTransaction);
|
|
372
|
+
parsedRecipients.length.should.equal(1);
|
|
373
|
+
parsedRecipients[0].address.should.equal(testData.recipients[0].address);
|
|
374
|
+
parsedRecipients[0].amount.should.equal(SEND_AMOUNT);
|
|
375
|
+
const rawTx = tx.toBroadcastFormat();
|
|
376
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
377
|
+
const rebuilder = factory.from(rawTx);
|
|
378
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
379
|
+
const rebuiltTx = await rebuilder.build();
|
|
380
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
381
|
+
});
|
|
382
|
+
it('should build Path 2b with ValidDuring expiration (production consolidation scenario)', async function () {
|
|
383
|
+
// Mirrors the real on-chain consolidation that failed: address index 10, wallet
|
|
384
|
+
// 67fe3f15..., txid JDbnybotg3axfjtB53LrnV1YtvGLFBVG8o2Xz5xX1m6Z.
|
|
385
|
+
// The recover() code sets ValidDuring when coinObjectsBalance=0 and
|
|
386
|
+
// fundsInAddressBalance>0 (Case 2). This test verifies both the expiration survives
|
|
387
|
+
// serialization and the PTB uses Path 2b (not the broken SplitCoins(GasCoin) path).
|
|
388
|
+
const GENESIS_CHAIN_ID = 'GAFpCCcRCxTdFfUEMbQbkLBaZy2RNiGAfvFBhMNpq2kT';
|
|
389
|
+
const SEND_AMOUNT = '1275170993710';
|
|
390
|
+
const ADDR_BAL = '1275177540910';
|
|
391
|
+
const gasDataNoPayment = {
|
|
392
|
+
...testData.gasDataWithoutGasPayment,
|
|
393
|
+
payment: [],
|
|
394
|
+
};
|
|
395
|
+
const txBuilder = factory.getTransferBuilder();
|
|
396
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
397
|
+
txBuilder.sender(testData.sender.address);
|
|
398
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: SEND_AMOUNT }]);
|
|
399
|
+
txBuilder.gasData(gasDataNoPayment);
|
|
400
|
+
txBuilder.fundsInAddressBalance(ADDR_BAL);
|
|
401
|
+
txBuilder.expiration({
|
|
402
|
+
ValidDuring: {
|
|
403
|
+
minEpoch: { Some: 1156 },
|
|
404
|
+
maxEpoch: { Some: 1157 },
|
|
405
|
+
minTimestamp: { None: null },
|
|
406
|
+
maxTimestamp: { None: null },
|
|
407
|
+
chain: GENESIS_CHAIN_ID,
|
|
408
|
+
nonce: 12345678,
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
const tx = await txBuilder.build();
|
|
412
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
413
|
+
const suiTx = tx;
|
|
414
|
+
suiTx.suiTransaction.gasData.payment.length.should.equal(0);
|
|
415
|
+
// Must use Path 2b (MoveCall first), never SplitCoins(GasCoin) first
|
|
416
|
+
const cmds = suiTx.suiTransaction.tx.transactions;
|
|
417
|
+
cmds[0].kind.should.equal('MoveCall', 'Path 2b must start with MoveCall(redeem_funds), not SplitCoins(GasCoin)');
|
|
418
|
+
cmds[0].target.should.equal('0x2::coin::redeem_funds');
|
|
419
|
+
cmds[cmds.length - 1].kind.should.equal('MergeCoins', 'Path 2b must end with MergeCoins to destroy 0-balance addrCoin');
|
|
420
|
+
// ValidDuring expiration must survive BCS round-trip
|
|
421
|
+
const rawTx = tx.toBroadcastFormat();
|
|
422
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
423
|
+
const rebuilder = factory.from(rawTx);
|
|
424
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
425
|
+
const rebuiltTx = await rebuilder.build();
|
|
426
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
427
|
+
const expiration = rebuiltTx.toJson().expiration?.ValidDuring;
|
|
428
|
+
should_1.default.exist(expiration, 'ValidDuring expiration must survive round-trip');
|
|
429
|
+
Number(expiration.minEpoch.Some).should.equal(1156);
|
|
430
|
+
Number(expiration.maxEpoch.Some).should.equal(1157);
|
|
431
|
+
});
|
|
432
|
+
it('should build a self-pay transfer with coin objects + address balance (Path 2c)', async function () {
|
|
433
|
+
// Regression test for COINS-331: when both gasData.payment (coin objects) and
|
|
434
|
+
// fundsInAddressBalance are set, Sui does NOT automatically merge address balance into
|
|
435
|
+
// the gas coin. Path 2c must explicitly call redeem_funds + MergeCoins(gas, [addrCoin])
|
|
436
|
+
// before SplitCoins so that the gas coin holds the full spendable amount.
|
|
437
|
+
const txBuilder = factory.getTransferBuilder();
|
|
438
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
439
|
+
txBuilder.sender(testData.sender.address);
|
|
440
|
+
txBuilder.send(testData.recipients);
|
|
441
|
+
txBuilder.gasData(testData.gasData); // non-empty payment — triggers Path 2c
|
|
442
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
443
|
+
const tx = await txBuilder.build();
|
|
444
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
445
|
+
const suiTx = tx;
|
|
446
|
+
// Path 2c PTB command sequence (for 2 recipients):
|
|
447
|
+
// 0: MoveCall(redeem_funds) — materialize addrCoin from address balance
|
|
448
|
+
// 1: MergeCoins(gas, [addrCoin])— gas coin = coinObjects + addrBal (full spendable amount)
|
|
449
|
+
// 2: SplitCoins(gas) — split for recipient 0
|
|
450
|
+
// 3: TransferObjects — send to recipient 0
|
|
451
|
+
// 4: SplitCoins(gas) — split for recipient 1
|
|
452
|
+
// 5: TransferObjects — send to recipient 1
|
|
453
|
+
const programmableTx = suiTx.suiTransaction.tx;
|
|
454
|
+
const cmds = programmableTx.transactions;
|
|
455
|
+
cmds[0].kind.should.equal('MoveCall', 'command 0 must be MoveCall(redeem_funds)');
|
|
456
|
+
cmds[0].target.should.equal('0x2::coin::redeem_funds');
|
|
457
|
+
cmds[1].kind.should.equal('MergeCoins', 'command 1 must be MergeCoins(gas, [addrCoin])');
|
|
458
|
+
cmds[2].kind.should.equal('SplitCoins', 'command 2 must be SplitCoins(gas, [amount0])');
|
|
459
|
+
cmds[3].kind.should.equal('TransferObjects');
|
|
460
|
+
cmds[4].kind.should.equal('SplitCoins', 'command 4 must be SplitCoins(gas, [amount1])');
|
|
461
|
+
cmds[5].kind.should.equal('TransferObjects');
|
|
462
|
+
// fundsInAddressBalance must be persisted in the serialized transaction
|
|
463
|
+
suiTx.suiTransaction.fundsInAddressBalance.should.equal(FUNDS_IN_ADDRESS_BALANCE);
|
|
464
|
+
const rawTx = tx.toBroadcastFormat();
|
|
465
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
466
|
+
// Round-trip: rebuilt transaction must be bit-for-bit identical
|
|
467
|
+
const rebuilder = factory.from(rawTx);
|
|
468
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
469
|
+
const rebuiltTx = await rebuilder.build();
|
|
470
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
471
|
+
});
|
|
472
|
+
it('should build a sponsored transfer with coin objects + address balance', async function () {
|
|
473
|
+
const inputObjects = testData.generateObjects(2);
|
|
474
|
+
const sponsoredGasData = {
|
|
475
|
+
...testData.gasData,
|
|
476
|
+
owner: testData.feePayer.address,
|
|
477
|
+
};
|
|
478
|
+
const txBuilder = factory.getTransferBuilder();
|
|
479
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
480
|
+
txBuilder.sender(testData.sender.address);
|
|
481
|
+
txBuilder.send(testData.recipients);
|
|
482
|
+
txBuilder.gasData(sponsoredGasData);
|
|
483
|
+
txBuilder.inputObjects(inputObjects);
|
|
484
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
485
|
+
const tx = await txBuilder.build();
|
|
486
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
487
|
+
const suiTx = tx;
|
|
488
|
+
suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
|
|
489
|
+
// Sponsored path: MoveCall(redeem_funds) + MergeCoins + SplitCoins
|
|
490
|
+
const programmableTx = suiTx.suiTransaction.tx;
|
|
491
|
+
programmableTx.transactions[0].kind.should.equal('MoveCall');
|
|
492
|
+
programmableTx.transactions[0].target.should.equal('0x2::coin::redeem_funds');
|
|
493
|
+
programmableTx.transactions[1].kind.should.equal('MergeCoins');
|
|
494
|
+
programmableTx.transactions[2].kind.should.equal('SplitCoins');
|
|
495
|
+
const rawTx = tx.toBroadcastFormat();
|
|
496
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
497
|
+
// Round-trip
|
|
498
|
+
const rebuilder = factory.from(rawTx);
|
|
499
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
500
|
+
const rebuiltTx = await rebuilder.build();
|
|
501
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
502
|
+
});
|
|
503
|
+
it('should build a sponsored transfer with address balance only (no coin inputObjects)', async function () {
|
|
504
|
+
const sponsoredGasData = {
|
|
505
|
+
...testData.gasData,
|
|
506
|
+
owner: testData.feePayer.address,
|
|
507
|
+
};
|
|
508
|
+
const txBuilder = factory.getTransferBuilder();
|
|
509
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
510
|
+
txBuilder.sender(testData.sender.address);
|
|
511
|
+
txBuilder.send(testData.recipients);
|
|
512
|
+
txBuilder.gasData(sponsoredGasData);
|
|
513
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
514
|
+
const tx = await txBuilder.build();
|
|
515
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
516
|
+
// Path 1b: withdrawal → redeem_funds → SplitCoins(addrCoin) → TransferObjects
|
|
517
|
+
// Sponsor's gas coins remain in gasData.payment; tx.gas is NOT used for the transfer amount.
|
|
518
|
+
const suiTx = tx;
|
|
519
|
+
suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
|
|
520
|
+
const programmableTx = suiTx.suiTransaction.tx;
|
|
521
|
+
programmableTx.transactions[0].kind.should.equal('MoveCall');
|
|
522
|
+
programmableTx.transactions[0].target.should.equal('0x2::coin::redeem_funds');
|
|
523
|
+
programmableTx.transactions[1].kind.should.equal('SplitCoins');
|
|
524
|
+
const rawTx = tx.toBroadcastFormat();
|
|
525
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
526
|
+
// Round-trip: rebuild from raw
|
|
527
|
+
const rebuilder = factory.from(rawTx);
|
|
528
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
529
|
+
const rebuiltTx = await rebuilder.build();
|
|
530
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
531
|
+
});
|
|
532
|
+
it('should build Path 1b send-all: sponsored addr-balance-only, no change (MergeCoins consumes addrCoin)', async function () {
|
|
533
|
+
// Reproduces the real on-chain failure: UnusedValueWithoutDrop { result_idx: 0 }
|
|
534
|
+
// Occurs when redeem_funds returns addrCoin, SplitCoins drains it completely, and the
|
|
535
|
+
// 0-balance source coin is never consumed. Fix: MergeCoins(gas, [addrCoin]) at the end.
|
|
536
|
+
const SEND_AMOUNT = '1000000'; // 0.001 SUI — same as the failing tx
|
|
537
|
+
const sponsoredGasData = {
|
|
538
|
+
...testData.gasData,
|
|
539
|
+
owner: testData.feePayer.address,
|
|
540
|
+
};
|
|
541
|
+
const txBuilder = factory.getTransferBuilder();
|
|
542
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
543
|
+
txBuilder.sender(testData.sender.address);
|
|
544
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: SEND_AMOUNT }]);
|
|
545
|
+
txBuilder.gasData(sponsoredGasData);
|
|
546
|
+
txBuilder.fundsInAddressBalance(SEND_AMOUNT); // send-all: balance == recipient amount
|
|
547
|
+
const tx = await txBuilder.build();
|
|
548
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
549
|
+
const suiTx = tx;
|
|
550
|
+
const cmds = suiTx.suiTransaction.tx.transactions;
|
|
551
|
+
// Expected command sequence for Path 1b send-all:
|
|
552
|
+
// 0: MoveCall (redeem_funds) — withdraw addrCoin
|
|
553
|
+
// 1: SplitCoins(addrCoin) — split recipient amount off addrCoin
|
|
554
|
+
// 2: TransferObjects([split]) — send to recipient
|
|
555
|
+
// 3: MergeCoins(gas, [addrCoin]) — consume the now-zero-balance addrCoin
|
|
556
|
+
cmds[0].kind.should.equal('MoveCall');
|
|
557
|
+
cmds[0].target.should.equal('0x2::coin::redeem_funds');
|
|
558
|
+
cmds[1].kind.should.equal('SplitCoins');
|
|
559
|
+
cmds[2].kind.should.equal('TransferObjects');
|
|
560
|
+
cmds[3].kind.should.equal('MergeCoins', 'expected MergeCoins to consume 0-balance addrCoin after send-all');
|
|
561
|
+
// Recipient parsing must not be affected by the trailing MergeCoins
|
|
562
|
+
const recipients = utils_1.default.getRecipients(suiTx.suiTransaction);
|
|
563
|
+
recipients.length.should.equal(1);
|
|
564
|
+
recipients[0].address.should.equal(testData.recipients[0].address);
|
|
565
|
+
recipients[0].amount.should.equal(SEND_AMOUNT);
|
|
566
|
+
// Round-trip
|
|
567
|
+
const rawTx = tx.toBroadcastFormat();
|
|
568
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
569
|
+
const rebuilder = factory.from(rawTx);
|
|
570
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
571
|
+
const rebuiltTx = await rebuilder.build();
|
|
572
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
573
|
+
});
|
|
574
|
+
it('should build Path 1b with change: sponsored addr-balance-only, excess returned to sender', async function () {
|
|
575
|
+
// fundsInAddressBalance exceeds the total recipient amount → change must be returned to
|
|
576
|
+
// the sender as an extra TransferObjects([addrCoin], sender). The transaction parser must
|
|
577
|
+
// skip this change transfer and only report actual recipients.
|
|
578
|
+
const SEND_AMOUNT = '100'; // each of the two testData.recipients gets 100
|
|
579
|
+
const EXCESS = '9999900'; // fundsInAddressBalance = 10_000_000, total send = 200
|
|
580
|
+
const FUNDS_BALANCE = (Number(SEND_AMOUNT) * testData.recipients.length + Number(EXCESS)).toString();
|
|
581
|
+
const sponsoredGasData = {
|
|
582
|
+
...testData.gasData,
|
|
583
|
+
owner: testData.feePayer.address,
|
|
584
|
+
};
|
|
585
|
+
const txBuilder = factory.getTransferBuilder();
|
|
586
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
587
|
+
txBuilder.sender(testData.sender.address);
|
|
588
|
+
txBuilder.send(testData.recipients); // 2 recipients × 100 MIST = 200 MIST total
|
|
589
|
+
txBuilder.gasData(sponsoredGasData);
|
|
590
|
+
txBuilder.fundsInAddressBalance(FUNDS_BALANCE); // 10_000_000 > 200 → has change
|
|
591
|
+
const tx = await txBuilder.build();
|
|
592
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
593
|
+
const suiTx = tx;
|
|
594
|
+
const cmds = suiTx.suiTransaction.tx.transactions;
|
|
595
|
+
// Expected sequence for Path 1b with change (2 recipients):
|
|
596
|
+
// 0: MoveCall (redeem_funds)
|
|
597
|
+
// 1: SplitCoins — recipient 0
|
|
598
|
+
// 2: TransferObjects — recipient 0
|
|
599
|
+
// 3: SplitCoins — recipient 1
|
|
600
|
+
// 4: TransferObjects — recipient 1
|
|
601
|
+
// 5: TransferObjects([addrCoin], sender) — change back to sender
|
|
602
|
+
cmds[0].kind.should.equal('MoveCall');
|
|
603
|
+
cmds[0].target.should.equal('0x2::coin::redeem_funds');
|
|
604
|
+
const lastCmd = cmds[cmds.length - 1];
|
|
605
|
+
lastCmd.kind.should.equal('TransferObjects', 'last command must be the change transfer');
|
|
606
|
+
// The last TransferObjects returns change to the *sender*, not a recipient
|
|
607
|
+
const changeAddrInput = suiTx.suiTransaction.tx.inputs[lastCmd.address.index];
|
|
608
|
+
const changeAddr = utils_1.default.getAddress(changeAddrInput);
|
|
609
|
+
changeAddr.should.equal(testData.sender.address, 'change must go back to sender');
|
|
610
|
+
// Parser must return only the actual recipients, not the change transfer
|
|
611
|
+
const recipients = utils_1.default.getRecipients(suiTx.suiTransaction);
|
|
612
|
+
recipients.length.should.equal(testData.recipients.length);
|
|
613
|
+
recipients[0].address.should.equal(testData.recipients[0].address);
|
|
614
|
+
recipients[0].amount.should.equal(SEND_AMOUNT);
|
|
615
|
+
recipients[1].address.should.equal(testData.recipients[1].address);
|
|
616
|
+
recipients[1].amount.should.equal(SEND_AMOUNT);
|
|
617
|
+
// Round-trip
|
|
618
|
+
const rawTx = tx.toBroadcastFormat();
|
|
619
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
620
|
+
const rebuilder = factory.from(rawTx);
|
|
621
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
622
|
+
const rebuiltTx = await rebuilder.build();
|
|
623
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
624
|
+
});
|
|
625
|
+
it('should build a sponsored tx gas paid from sponsor address balance (empty payment)', async function () {
|
|
626
|
+
const inputObjects = testData.generateObjects(1);
|
|
627
|
+
const sponsoredGasDataNoPayment = {
|
|
628
|
+
payment: [],
|
|
629
|
+
owner: testData.feePayer.address,
|
|
630
|
+
price: testData.gasData.price,
|
|
631
|
+
budget: testData.gasData.budget,
|
|
632
|
+
};
|
|
633
|
+
const txBuilder = factory.getTransferBuilder();
|
|
634
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
635
|
+
txBuilder.sender(testData.sender.address);
|
|
636
|
+
txBuilder.send(testData.recipients);
|
|
637
|
+
txBuilder.gasData(sponsoredGasDataNoPayment);
|
|
638
|
+
txBuilder.inputObjects(inputObjects);
|
|
639
|
+
const tx = await txBuilder.build();
|
|
640
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
641
|
+
const suiTx = tx;
|
|
642
|
+
suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
|
|
643
|
+
suiTx.suiTransaction.gasData.payment.length.should.equal(0);
|
|
644
|
+
// Sponsored path with coin objects, no address balance withdrawal
|
|
645
|
+
const programmableTx = suiTx.suiTransaction.tx;
|
|
646
|
+
programmableTx.transactions[0].kind.should.equal('SplitCoins');
|
|
647
|
+
const rawTx = tx.toBroadcastFormat();
|
|
648
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
649
|
+
});
|
|
650
|
+
it('should round-trip a self-pay transfer with Epoch expiration via fromBytes', async function () {
|
|
651
|
+
// Regression test for the BigInt round-trip bug:
|
|
652
|
+
// BCS.U64 deserializes u64 as BigInt, but the previous superstruct schema used integer()
|
|
653
|
+
// which rejected BigInt, causing fromBytes() to throw a StructError at "expiration".
|
|
654
|
+
// StringEncodedBigint now accepts string | number | bigint, fixing the round-trip.
|
|
655
|
+
const gasDataNoPayment = {
|
|
656
|
+
...testData.gasDataWithoutGasPayment,
|
|
657
|
+
payment: [],
|
|
658
|
+
};
|
|
659
|
+
const txBuilder = factory.getTransferBuilder();
|
|
660
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
661
|
+
txBuilder.sender(testData.sender.address);
|
|
662
|
+
txBuilder.send(testData.recipients);
|
|
663
|
+
txBuilder.gasData(gasDataNoPayment);
|
|
664
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
665
|
+
txBuilder.expiration({ Epoch: 324 }); // number input
|
|
666
|
+
const tx = await txBuilder.build();
|
|
667
|
+
const rawTx = tx.toBroadcastFormat();
|
|
668
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
669
|
+
// fromBytes must not throw StructError — this was the failing case before the fix
|
|
670
|
+
should_1.default.doesNotThrow(() => {
|
|
671
|
+
const rebuilder = factory.from(rawTx);
|
|
672
|
+
should_1.default.exist(rebuilder);
|
|
673
|
+
});
|
|
674
|
+
// Full round-trip: rebuilt tx must serialize identically
|
|
675
|
+
const rebuilder = factory.from(rawTx);
|
|
676
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
677
|
+
const rebuiltTx = await rebuilder.build();
|
|
678
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
679
|
+
// Epoch value must survive the round-trip regardless of BigInt/number representation
|
|
680
|
+
const rebuiltJson = rebuiltTx.toJson();
|
|
681
|
+
const epochVal = rebuiltJson.expiration?.Epoch;
|
|
682
|
+
should_1.default.exist(epochVal);
|
|
683
|
+
Number(epochVal).should.equal(324);
|
|
684
|
+
});
|
|
685
|
+
it('should round-trip a self-pay transfer with ValidDuring expiration via fromBytes', async function () {
|
|
686
|
+
// Verifies the full 6-field ValidDuringExpiration BCS schema:
|
|
687
|
+
// minEpoch/maxEpoch as Option<u64>, minTimestamp/maxTimestamp as Option<u64> (None),
|
|
688
|
+
// chain as 32-byte Base58 ObjectDigest, nonce as u32.
|
|
689
|
+
// Uses a real mainnet genesis checkpoint digest (32 bytes, Base58).
|
|
690
|
+
const GENESIS_CHAIN_ID = 'GAFpCCcRCxTdFfUEMbQbkLBaZy2RNiGAfvFBhMNpq2kT';
|
|
691
|
+
const FUNDS_IN_ADDRESS_BALANCE = '5000000000';
|
|
692
|
+
const gasDataNoPayment = {
|
|
693
|
+
...testData.gasDataWithoutGasPayment,
|
|
694
|
+
payment: [],
|
|
695
|
+
};
|
|
696
|
+
const txBuilder = factory.getTransferBuilder();
|
|
697
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
698
|
+
txBuilder.sender(testData.sender.address);
|
|
699
|
+
txBuilder.send(testData.recipients);
|
|
700
|
+
txBuilder.gasData(gasDataNoPayment);
|
|
701
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
702
|
+
txBuilder.expiration({
|
|
703
|
+
ValidDuring: {
|
|
704
|
+
minEpoch: { Some: 500 },
|
|
705
|
+
maxEpoch: { Some: 501 },
|
|
706
|
+
minTimestamp: { None: null },
|
|
707
|
+
maxTimestamp: { None: null },
|
|
708
|
+
chain: GENESIS_CHAIN_ID,
|
|
709
|
+
nonce: 0xdeadbeef,
|
|
710
|
+
},
|
|
711
|
+
});
|
|
712
|
+
const tx = await txBuilder.build();
|
|
713
|
+
const rawTx = tx.toBroadcastFormat();
|
|
714
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
715
|
+
// fromBytes must not throw — ValidDuring fields must survive deserialization
|
|
716
|
+
const rebuilder = factory.from(rawTx);
|
|
717
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
718
|
+
const rebuiltTx = await rebuilder.build();
|
|
719
|
+
// BCS round-trip: serialized bytes must be identical
|
|
720
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
721
|
+
// All ValidDuring fields must survive the round-trip
|
|
722
|
+
const expiration = rebuiltTx.toJson().expiration?.ValidDuring;
|
|
723
|
+
should_1.default.exist(expiration);
|
|
724
|
+
Number(expiration.minEpoch?.Some ?? expiration.minEpoch).should.equal(500);
|
|
725
|
+
Number(expiration.maxEpoch?.Some ?? expiration.maxEpoch).should.equal(501);
|
|
726
|
+
expiration.chain.should.equal(GENESIS_CHAIN_ID);
|
|
727
|
+
Number(expiration.nonce).should.equal(0xdeadbeef);
|
|
728
|
+
});
|
|
729
|
+
});
|
|
730
|
+
describe('large amounts exceeding Number.MAX_SAFE_INTEGER', () => {
|
|
731
|
+
// Number.MAX_SAFE_INTEGER = 9007199254740991.
|
|
732
|
+
// Using Number() for amounts above this silently rounds to the nearest representable float.
|
|
733
|
+
// 9007199254740993 (MAX_SAFE_INTEGER + 2) is NOT exactly representable as a JS Number — it
|
|
734
|
+
// rounds down to 9007199254740992 — so BCS would encode the wrong value.
|
|
735
|
+
// BigInt preserves the exact value and is the correct type for BCS u64 encoding.
|
|
736
|
+
//
|
|
737
|
+
// The core check in each test is tx.outputs[0].value === LARGE_AMOUNT: this reads from the
|
|
738
|
+
// in-memory builder state (a BigInt, not BCS-decoded), so it accurately distinguishes
|
|
739
|
+
// BigInt() vs Number() encoding at build time.
|
|
740
|
+
const LARGE_AMOUNT = '9007199254740993'; // MAX_SAFE_INTEGER + 2
|
|
741
|
+
it('should build a self-pay transfer (Path 2) with amount > Number.MAX_SAFE_INTEGER and encode it precisely', async function () {
|
|
742
|
+
const txBuilder = factory.getTransferBuilder();
|
|
743
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
744
|
+
txBuilder.sender(testData.sender.address);
|
|
745
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: LARGE_AMOUNT }]);
|
|
746
|
+
txBuilder.gasData(testData.gasData);
|
|
747
|
+
const tx = await txBuilder.build();
|
|
748
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
749
|
+
// With Number() the amount would be silently rounded to 9007199254740992 — BigInt preserves the exact value
|
|
750
|
+
tx.outputs.length.should.equal(1);
|
|
751
|
+
tx.outputs[0].value.should.equal(LARGE_AMOUNT);
|
|
752
|
+
const rawTx = tx.toBroadcastFormat();
|
|
753
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
754
|
+
});
|
|
755
|
+
it('should build a sponsored transfer with coin objects (Path 1a) with amount > Number.MAX_SAFE_INTEGER and encode it precisely', async function () {
|
|
756
|
+
const inputObjects = testData.generateObjects(2);
|
|
757
|
+
const sponsoredGasData = {
|
|
758
|
+
...testData.gasData,
|
|
759
|
+
owner: testData.feePayer.address,
|
|
760
|
+
};
|
|
761
|
+
const txBuilder = factory.getTransferBuilder();
|
|
762
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
763
|
+
txBuilder.sender(testData.sender.address);
|
|
764
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: LARGE_AMOUNT }]);
|
|
765
|
+
txBuilder.gasData(sponsoredGasData);
|
|
766
|
+
txBuilder.inputObjects(inputObjects);
|
|
767
|
+
const tx = await txBuilder.build();
|
|
768
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
769
|
+
// With Number() the amount would be silently rounded to 9007199254740992 — BigInt preserves the exact value
|
|
770
|
+
tx.outputs.length.should.equal(1);
|
|
771
|
+
tx.outputs[0].value.should.equal(LARGE_AMOUNT);
|
|
772
|
+
const rawTx = tx.toBroadcastFormat();
|
|
773
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
774
|
+
});
|
|
775
|
+
it('should build a sponsored addr-balance-only transfer (Path 1b) with amount > Number.MAX_SAFE_INTEGER and round-trip correctly', async function () {
|
|
776
|
+
const sponsoredGasData = {
|
|
777
|
+
...testData.gasData,
|
|
778
|
+
owner: testData.feePayer.address,
|
|
779
|
+
};
|
|
780
|
+
const txBuilder = factory.getTransferBuilder();
|
|
781
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
782
|
+
txBuilder.sender(testData.sender.address);
|
|
783
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: LARGE_AMOUNT }]);
|
|
784
|
+
txBuilder.gasData(sponsoredGasData);
|
|
785
|
+
txBuilder.fundsInAddressBalance(LARGE_AMOUNT);
|
|
786
|
+
const tx = await txBuilder.build();
|
|
787
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
788
|
+
// With Number() the amount would be silently rounded to 9007199254740992 — BigInt preserves the exact value
|
|
789
|
+
tx.outputs.length.should.equal(1);
|
|
790
|
+
tx.outputs[0].value.should.equal(LARGE_AMOUNT);
|
|
791
|
+
const rawTx = tx.toBroadcastFormat();
|
|
792
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
793
|
+
// Full round-trip: rebuilding from BCS bytes must produce identical bytes
|
|
794
|
+
const rebuilder = factory.from(rawTx);
|
|
795
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
796
|
+
const rebuiltTx = await rebuilder.build();
|
|
797
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
798
|
+
const recipients = utils_1.default.getRecipients(rebuiltTx.suiTransaction);
|
|
799
|
+
recipients[0].amount.should.equal(LARGE_AMOUNT);
|
|
800
|
+
});
|
|
801
|
+
});
|
|
802
|
+
describe('prod address balance consolidation (CECHO-1210)', () => {
|
|
803
|
+
// Failed prod consolidation 6a19cb8bcd4751dbd891a722ee04e552 (txRequest ee5d60d7-fa53-4fa4-adcf-26435c9317bf).
|
|
804
|
+
// Broadcast failed with stale coin object version; the amount must still encode losslessly.
|
|
805
|
+
const CONSOLIDATION_AMOUNT = '18536797842613700'; // ~18.5M SUI in MIST (sendAccounting.amountString)
|
|
806
|
+
const CONSOLIDATION_SENDER = '0x46a53e2712561f4e0d8272bd27a396b6bf9325f92f34b949041b8783d57469dd';
|
|
807
|
+
const CONSOLIDATION_RECIPIENT = '0x3da2cb67c887c9a03d1052d486733a77105824f7413fc3cbbe3641d4b67af102';
|
|
808
|
+
it('should accept the prod consolidation amount in isValidAmount', function () {
|
|
809
|
+
utils_1.default.isValidAmount(CONSOLIDATION_AMOUNT).should.be.true();
|
|
810
|
+
Number.isSafeInteger(Number(CONSOLIDATION_AMOUNT)).should.be.false();
|
|
811
|
+
});
|
|
812
|
+
it('should build address-balance-only consolidation with exact prod amount (Path 2, empty payment)', async function () {
|
|
813
|
+
const gasDataNoPayment = {
|
|
814
|
+
...testData.gasDataWithoutGasPayment,
|
|
815
|
+
payment: [],
|
|
816
|
+
};
|
|
817
|
+
const txBuilder = factory.getTransferBuilder();
|
|
818
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
819
|
+
txBuilder.sender(CONSOLIDATION_SENDER);
|
|
820
|
+
txBuilder.send([{ address: CONSOLIDATION_RECIPIENT, amount: CONSOLIDATION_AMOUNT }]);
|
|
821
|
+
txBuilder.gasData(gasDataNoPayment);
|
|
822
|
+
txBuilder.fundsInAddressBalance(CONSOLIDATION_AMOUNT);
|
|
823
|
+
const tx = await txBuilder.build();
|
|
824
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
825
|
+
tx.outputs.length.should.equal(1);
|
|
826
|
+
tx.outputs[0].should.deepEqual({
|
|
827
|
+
address: CONSOLIDATION_RECIPIENT,
|
|
828
|
+
value: CONSOLIDATION_AMOUNT,
|
|
829
|
+
coin: 'tsui',
|
|
830
|
+
});
|
|
831
|
+
tx.inputs.length.should.equal(1);
|
|
832
|
+
tx.inputs[0].value.should.equal(CONSOLIDATION_AMOUNT);
|
|
833
|
+
const rawTx = tx.toBroadcastFormat();
|
|
834
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
835
|
+
const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
|
|
836
|
+
const recipients = utils_1.default.getRecipients(deserialized);
|
|
837
|
+
recipients.length.should.equal(1);
|
|
838
|
+
recipients[0].address.should.equal(CONSOLIDATION_RECIPIENT);
|
|
839
|
+
recipients[0].amount.should.equal(CONSOLIDATION_AMOUNT);
|
|
840
|
+
});
|
|
841
|
+
it('should build address-balance consolidation with coin objects and exact prod amount (Path 2)', async function () {
|
|
842
|
+
// Prod failure referenced stale gas/coin object versions between sign and broadcast.
|
|
843
|
+
// Builder must still encode the full consolidation amount in SplitCoins.
|
|
844
|
+
const txBuilder = factory.getTransferBuilder();
|
|
845
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
846
|
+
txBuilder.sender(CONSOLIDATION_SENDER);
|
|
847
|
+
txBuilder.send([{ address: CONSOLIDATION_RECIPIENT, amount: CONSOLIDATION_AMOUNT }]);
|
|
848
|
+
txBuilder.gasData({ ...testData.gasData, owner: CONSOLIDATION_SENDER });
|
|
849
|
+
txBuilder.fundsInAddressBalance(CONSOLIDATION_AMOUNT);
|
|
850
|
+
const tx = await txBuilder.build();
|
|
851
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
852
|
+
tx.outputs[0].value.should.equal(CONSOLIDATION_AMOUNT);
|
|
853
|
+
tx.inputs[0].value.should.equal(CONSOLIDATION_AMOUNT);
|
|
854
|
+
const rawTx = tx.toBroadcastFormat();
|
|
855
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
856
|
+
const rebuilder = factory.from(rawTx);
|
|
857
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
858
|
+
const rebuiltTx = await rebuilder.build();
|
|
859
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
860
|
+
const recipients = utils_1.default.getRecipients(rebuiltTx.suiTransaction);
|
|
861
|
+
recipients[0].address.should.equal(CONSOLIDATION_RECIPIENT);
|
|
862
|
+
recipients[0].amount.should.equal(CONSOLIDATION_AMOUNT);
|
|
863
|
+
});
|
|
864
|
+
});
|
|
865
|
+
describe('BalanceWithdrawal BCS encoding (FundsWithdrawal format)', () => {
|
|
866
|
+
const AMOUNT = '100000000'; // 0.1 SUI in MIST
|
|
867
|
+
const sponsoredGasData = {
|
|
868
|
+
...testData.gasData,
|
|
869
|
+
owner: testData.feePayer.address,
|
|
870
|
+
};
|
|
871
|
+
async function buildSponsoredTxWithAddressBalance() {
|
|
872
|
+
const txBuilder = factory.getTransferBuilder();
|
|
873
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
874
|
+
txBuilder.sender(testData.sender.address);
|
|
875
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
|
|
876
|
+
txBuilder.gasData(sponsoredGasData);
|
|
877
|
+
txBuilder.fundsInAddressBalance(AMOUNT);
|
|
878
|
+
return txBuilder.build();
|
|
879
|
+
}
|
|
880
|
+
it('should encode BalanceWithdrawal input with FundsWithdrawal structure (reservation/typeArg/withdrawFrom)', async function () {
|
|
881
|
+
const tx = await buildSponsoredTxWithAddressBalance();
|
|
882
|
+
const suiTx = tx;
|
|
883
|
+
const inputs = suiTx.suiTransaction.tx.inputs;
|
|
884
|
+
const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
885
|
+
should_1.default.exist(bwInput, 'BalanceWithdrawal input must be present');
|
|
886
|
+
const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
|
|
887
|
+
should_1.default.exist(bw.reservation, 'reservation field must exist');
|
|
888
|
+
should_1.default.exist(bw.reservation.MaxAmountU64, 'reservation.MaxAmountU64 must exist');
|
|
889
|
+
bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
|
|
890
|
+
should_1.default.exist(bw.typeArg, 'typeArg field must exist');
|
|
891
|
+
should_1.default.exist(bw.typeArg.Balance, 'typeArg.Balance must exist');
|
|
892
|
+
should_1.default.exist(bw.withdrawFrom, 'withdrawFrom field must exist');
|
|
893
|
+
should_1.default.exist(bw.withdrawFrom.Sender !== undefined || bw.withdrawFrom.Sponsor !== undefined, 'withdrawFrom must be Sender or Sponsor');
|
|
894
|
+
// Old format fields must NOT exist directly on bw
|
|
895
|
+
should_1.default.not.exist(bw.amount, 'old "amount" field must not exist on BalanceWithdrawal');
|
|
896
|
+
should_1.default.not.exist(bw.type_, 'old "type_" field must not exist on BalanceWithdrawal');
|
|
897
|
+
});
|
|
898
|
+
it('should produce BCS bytes that decode back to FundsWithdrawal with correct amount', async function () {
|
|
899
|
+
const tx = await buildSponsoredTxWithAddressBalance();
|
|
900
|
+
const rawTx = tx.toBroadcastFormat();
|
|
901
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
902
|
+
const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
|
|
903
|
+
const inputs = deserialized.tx.inputs;
|
|
904
|
+
const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
905
|
+
should_1.default.exist(bwInput, 'BalanceWithdrawal must be present in deserialized inputs');
|
|
906
|
+
const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
|
|
907
|
+
// FundsWithdrawal structure (not old {amount, type_})
|
|
908
|
+
should_1.default.exist(bw.reservation, 'reservation must survive BCS round-trip');
|
|
909
|
+
should_1.default.exist(bw.reservation.MaxAmountU64, 'MaxAmountU64 must survive BCS round-trip');
|
|
910
|
+
bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
|
|
911
|
+
should_1.default.exist(bw.typeArg, 'typeArg must survive BCS round-trip');
|
|
912
|
+
should_1.default.exist(bw.typeArg.Balance, 'typeArg.Balance must survive BCS round-trip');
|
|
913
|
+
should_1.default.exist(bw.withdrawFrom, 'withdrawFrom must survive BCS round-trip');
|
|
914
|
+
});
|
|
915
|
+
it('should serialize toJson() without a BigInt replacer (no TypeError)', async function () {
|
|
916
|
+
const tx = await buildSponsoredTxWithAddressBalance();
|
|
917
|
+
should_1.default.doesNotThrow(() => JSON.stringify(tx.toJson()), 'JSON.stringify(tx.toJson()) must not throw — BalanceWithdrawal amount must not be stored as BigInt');
|
|
918
|
+
});
|
|
919
|
+
it('should preserve fundsInAddressBalance amount through full round-trip', async function () {
|
|
920
|
+
const tx = await buildSponsoredTxWithAddressBalance();
|
|
921
|
+
const rawTx = tx.toBroadcastFormat();
|
|
922
|
+
const rebuilder = factory.from(rawTx);
|
|
923
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
924
|
+
const rebuiltTx = await rebuilder.build();
|
|
925
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
926
|
+
const suiTx = rebuiltTx;
|
|
927
|
+
const inputs = suiTx.suiTransaction.tx.inputs;
|
|
928
|
+
const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
929
|
+
should_1.default.exist(bwInput);
|
|
930
|
+
const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
|
|
931
|
+
bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
|
|
932
|
+
});
|
|
933
|
+
it('should build Path 2b: self-pay, empty payment — uses withdrawal+redeem_funds instead of SplitCoins(GasCoin)', async function () {
|
|
934
|
+
// With gasData.payment=[] the runtime exposes only the gas-budget amount via GasCoin for
|
|
935
|
+
// PTB SplitCoins operations. SplitCoins(GasCoin, [large_amount]) always fails with
|
|
936
|
+
// InsufficientCoinBalance (confirmed by production failures JDbnybotg3ax..., ATUbeLX3...).
|
|
937
|
+
// Path 2b fixes this by withdrawing from the address accumulator via redeem_funds,
|
|
938
|
+
// splitting from that coin object, and merging the 0-balance remainder into GasCoin.
|
|
939
|
+
const selfPayNoPayment = { ...testData.gasDataWithoutGasPayment, payment: [] };
|
|
940
|
+
const txBuilder = factory.getTransferBuilder();
|
|
941
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
942
|
+
txBuilder.sender(testData.sender.address);
|
|
943
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
|
|
944
|
+
txBuilder.gasData(selfPayNoPayment);
|
|
945
|
+
txBuilder.fundsInAddressBalance(AMOUNT);
|
|
946
|
+
const tx = await txBuilder.build();
|
|
947
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
948
|
+
const suiTx = tx;
|
|
949
|
+
// Gas owner must equal sender (self-pay)
|
|
950
|
+
suiTx.suiTransaction.gasData.owner.should.equal(testData.sender.address);
|
|
951
|
+
// Payment must be empty — gas funded from address balance by the runtime
|
|
952
|
+
suiTx.suiTransaction.gasData.payment.length.should.equal(0);
|
|
953
|
+
// Path 2b: BalanceWithdrawal input MUST be present (withdrawal+redeem_funds approach)
|
|
954
|
+
const inputs = suiTx.suiTransaction.tx.inputs;
|
|
955
|
+
const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
956
|
+
should_1.default.exist(bwInput, 'Path 2b: BalanceWithdrawal input must be present');
|
|
957
|
+
const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
|
|
958
|
+
bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
|
|
959
|
+
// First command must be MoveCall(redeem_funds), NOT SplitCoins(GasCoin)
|
|
960
|
+
const commands = suiTx.suiTransaction.tx.transactions;
|
|
961
|
+
commands[0].kind.should.equal('MoveCall');
|
|
962
|
+
commands[0].target.should.equal('0x2::coin::redeem_funds');
|
|
963
|
+
// Followed by: SplitCoins(addrCoin), TransferObjects, MergeCoins(GasCoin, addrCoin)
|
|
964
|
+
commands[1].kind.should.equal('SplitCoins');
|
|
965
|
+
commands[2].kind.should.equal('TransferObjects');
|
|
966
|
+
commands[3].kind.should.equal('MergeCoins');
|
|
967
|
+
const rawTx = tx.toBroadcastFormat();
|
|
968
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
969
|
+
const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
|
|
970
|
+
deserialized.sender.should.equal(testData.sender.address);
|
|
971
|
+
deserialized.gasData.owner.should.equal(testData.sender.address);
|
|
972
|
+
deserialized.gasData.payment.length.should.equal(0);
|
|
973
|
+
// BalanceWithdrawal must survive BCS round-trip
|
|
974
|
+
const decodedInputs = deserialized.tx.inputs;
|
|
975
|
+
const decodedBwInput = decodedInputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
976
|
+
should_1.default.exist(decodedBwInput, 'BalanceWithdrawal must survive BCS round-trip for Path 2b');
|
|
977
|
+
const rebuilder = factory.from(rawTx);
|
|
978
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
979
|
+
const rebuiltTx = await rebuilder.build();
|
|
980
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
981
|
+
});
|
|
982
|
+
it('should build Path 2b with ValidDuring expiration (self-pay, empty payment)', async function () {
|
|
983
|
+
// Path 2b with ValidDuring expiration — required when gasData.payment=[] to prevent
|
|
984
|
+
// replay attacks. Uses withdrawal+redeem_funds to materialise transfer amount from the
|
|
985
|
+
// address accumulator, NOT SplitCoins(GasCoin) which fails with InsufficientCoinBalance.
|
|
986
|
+
const GENESIS_CHAIN_ID = 'GAFpCCcRCxTdFfUEMbQbkLBaZy2RNiGAfvFBhMNpq2kT';
|
|
987
|
+
const selfPayNoPayment = { ...testData.gasDataWithoutGasPayment, payment: [] };
|
|
988
|
+
const txBuilder = factory.getTransferBuilder();
|
|
989
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
990
|
+
txBuilder.sender(testData.sender.address);
|
|
991
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
|
|
992
|
+
txBuilder.gasData(selfPayNoPayment);
|
|
993
|
+
txBuilder.fundsInAddressBalance(AMOUNT);
|
|
994
|
+
txBuilder.expiration({
|
|
995
|
+
ValidDuring: {
|
|
996
|
+
minEpoch: { Some: 500 },
|
|
997
|
+
maxEpoch: { Some: 501 },
|
|
998
|
+
minTimestamp: { None: null },
|
|
999
|
+
maxTimestamp: { None: null },
|
|
1000
|
+
chain: GENESIS_CHAIN_ID,
|
|
1001
|
+
nonce: 0xdeadbeef,
|
|
1002
|
+
},
|
|
1003
|
+
});
|
|
1004
|
+
const tx = await txBuilder.build();
|
|
1005
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
1006
|
+
const suiTx = tx;
|
|
1007
|
+
// Self-pay: owner === sender, payment empty
|
|
1008
|
+
suiTx.suiTransaction.gasData.owner.should.equal(testData.sender.address);
|
|
1009
|
+
suiTx.suiTransaction.gasData.payment.length.should.equal(0);
|
|
1010
|
+
// Path 2b: BalanceWithdrawal input MUST be present
|
|
1011
|
+
const inputs = suiTx.suiTransaction.tx.inputs;
|
|
1012
|
+
const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
1013
|
+
should_1.default.exist(bwInput, 'Path 2b: BalanceWithdrawal input must be present');
|
|
1014
|
+
// First command: MoveCall(redeem_funds), NOT SplitCoins(GasCoin)
|
|
1015
|
+
const commands = suiTx.suiTransaction.tx.transactions;
|
|
1016
|
+
commands[0].kind.should.equal('MoveCall');
|
|
1017
|
+
commands[0].target.should.equal('0x2::coin::redeem_funds');
|
|
1018
|
+
const rawTx = tx.toBroadcastFormat();
|
|
1019
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
1020
|
+
const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
|
|
1021
|
+
deserialized.sender.should.equal(testData.sender.address);
|
|
1022
|
+
deserialized.gasData.payment.length.should.equal(0);
|
|
1023
|
+
const expiration = deserialized.expiration?.ValidDuring;
|
|
1024
|
+
should_1.default.exist(expiration, 'ValidDuring expiration must survive BCS round-trip');
|
|
1025
|
+
Number(expiration.minEpoch?.Some ?? expiration.minEpoch).should.equal(500);
|
|
1026
|
+
Number(expiration.maxEpoch?.Some ?? expiration.maxEpoch).should.equal(501);
|
|
1027
|
+
expiration.chain.should.equal(GENESIS_CHAIN_ID);
|
|
1028
|
+
Number(expiration.nonce).should.equal(0xdeadbeef);
|
|
1029
|
+
// BalanceWithdrawal must survive BCS round-trip
|
|
1030
|
+
const decodedInputs = deserialized.tx.inputs;
|
|
1031
|
+
const decodedBwInput = decodedInputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
1032
|
+
should_1.default.exist(decodedBwInput, 'BalanceWithdrawal must survive BCS round-trip for Path 2b');
|
|
1033
|
+
const rebuilder = factory.from(rawTx);
|
|
1034
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
1035
|
+
const rebuiltTx = await rebuilder.build();
|
|
1036
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
1037
|
+
});
|
|
1038
|
+
it('should build and correctly decode a MoveCall to 0x2::coin::redeem_funds with BalanceWithdrawal arg', async function () {
|
|
1039
|
+
const tx = await buildSponsoredTxWithAddressBalance();
|
|
1040
|
+
const suiTx = tx;
|
|
1041
|
+
const commands = suiTx.suiTransaction.tx.transactions;
|
|
1042
|
+
commands[0].kind.should.equal('MoveCall');
|
|
1043
|
+
commands[0].target.should.equal('0x2::coin::redeem_funds');
|
|
1044
|
+
commands[0].typeArguments[0].should.equal('0x2::sui::SUI');
|
|
1045
|
+
// The argument to redeem_funds must reference the BalanceWithdrawal input (index 0)
|
|
1046
|
+
const arg = commands[0].arguments[0];
|
|
1047
|
+
arg.kind.should.equal('Input');
|
|
1048
|
+
arg.index.should.equal(0);
|
|
1049
|
+
arg.type.should.equal('object');
|
|
1050
|
+
const rawTx = tx.toBroadcastFormat();
|
|
1051
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
1052
|
+
});
|
|
1053
|
+
});
|
|
1054
|
+
});
|
|
1055
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmZXJCdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC91bml0L3RyYW5zYWN0aW9uQnVpbGRlci90cmFuc2ZlckJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsNERBQXlEO0FBQ3pELDhEQUFnRDtBQUNoRCxvREFBNEI7QUFDNUIsbURBQXVEO0FBQ3ZELG1FQUEyQztBQUMzQyw4REFBNkU7QUFDN0Usa0RBQTZGO0FBQzdGLDBEQUErRTtBQUUvRSxRQUFRLENBQUMsc0JBQXNCLEVBQUUsR0FBRyxFQUFFO0lBQ3BDLE1BQU0sT0FBTyxHQUFHLElBQUEscUNBQWlCLEVBQUMsTUFBTSxDQUFDLENBQUM7SUFFMUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUU7UUFDdkIsRUFBRSxDQUFDLDRCQUE0QixFQUFFLEtBQUs7WUFDcEMsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDL0MsU0FBUyxDQUFDLElBQUksQ0FBQywwQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM1QyxTQUFTLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDMUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDcEMsTUFBTSxFQUFFLEdBQUcsTUFBTSxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbkMsZ0JBQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSwwQkFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNDLEVBQXNELENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxPQUFRLENB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QUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUUzRCxvRkFBb0Y7WUFDcEYsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNyQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDL0IsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFCLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUVoQyxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUNyQyxnQkFBTSxDQUFDLEtBQUssQ0FBQyxlQUFLLENBQUMscUJBQXFCLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDekQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgZ2V0QnVpbGRlckZhY3RvcnkgfSBmcm9tICcuLi9nZXRCdWlsZGVyRmFjdG9yeSc7XG5pbXBvcnQgKiBhcyB0ZXN0RGF0YSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvc3VpJztcbmltcG9ydCBzaG91bGQgZnJvbSAnc2hvdWxkJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uVHlwZSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB1dGlscyBmcm9tICcuLi8uLi8uLi9zcmMvbGliL3V0aWxzJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uIGFzIFN1aVRyYW5zYWN0aW9uIH0gZnJvbSAnLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbic7XG5pbXBvcnQgeyBTdWlUcmFuc2FjdGlvblR5cGUsIFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24gfSBmcm9tICcuLi8uLi8uLi9zcmMvbGliL2lmYWNlJztcbmltcG9ydCB7IE1BWF9DT01NQU5EX0FSR1MsIE1BWF9HQVNfT0JKRUNUUyB9IGZyb20gJy4uLy4uLy4uL3NyYy9saWIvY29uc3RhbnRzJztcblxuZGVzY3JpYmUoJ1N1aSBUcmFuc2ZlciBCdWlsZGVyJywgKCkgPT4ge1xuICBjb25zdCBmYWN0b3J5ID0gZ2V0QnVpbGRlckZhY3RvcnkoJ3RzdWknKTtcblxuICBkZXNjcmliZSgnU3VjY2VlZCcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgdHJhbnNmZXIgdHgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YSh0ZXN0RGF0YS5nYXNEYXRhKTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuICAgICAgKHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+KS5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLnBheW1lbnQhLnNob3VsZC5kZWVwRXF1YWwoXG4gICAgICAgIHRlc3REYXRhLmNvaW5zR2FzUGF5bWVudFxuICAgICAgKTtcblxuICAgICAgdHguaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICB0eC5pbnB1dHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLFxuICAgICAgICB2YWx1ZTogKHRlc3REYXRhLkFNT1VOVCAqIDIpLnRvU3RyaW5nKCksXG4gICAgICAgIGNvaW46ICd0c3VpJyxcbiAgICAgIH0pO1xuICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDIpO1xuICAgICAgdHgub3V0cHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLFxuICAgICAgICB2YWx1ZTogdGVzdERhdGEucmVjaXBpZW50c1swXS5hbW91bnQsXG4gICAgICAgIGNvaW46ICd0c3VpJyxcbiAgICAgIH0pO1xuICAgICAgdHgub3V0cHV0c1sxXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1sxXS5hZGRyZXNzLFxuICAgICAgICB2YWx1ZTogdGVzdERhdGEucmVjaXBpZW50c1sxXS5hbW91bnQsXG4gICAgICAgIGNvaW46ICd0c3VpJyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgICAgc2hvdWxkLmVxdWFsKHJhd1R4LCB0ZXN0RGF0YS5UUkFOU0ZFUik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc3BvbnNvcmVkIHRyYW5zZmVyIHR4IHdpdGggaW5wdXRPYmplY3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW5wdXRPYmplY3RzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgb2JqZWN0SWQ6ICcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4JyxcbiAgICAgICAgICB2ZXJzaW9uOiAxMDAsXG4gICAgICAgICAgZGlnZXN0OiAnMkI4WEtRSjdtZnhRUFVXcUpKQUdqekJBeml2a1dLcTJjRWEzVzhMTHoxeUInLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgb2JqZWN0SWQ6ICcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBhYmNkZWYxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyJyxcbiAgICAgICAgICB2ZXJzaW9uOiAyMDAsXG4gICAgICAgICAgZGlnZXN0OiAnRG9Kd1h1ejlvVTVZNXY1dkJSaVRnaXNWVFF1WlFMbUhaV2VxSnp6RDVRVUUnLFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgLy8gQ3JlYXRlIGdhcyBkYXRhIHdpdGggZGlmZmVyZW50IG93bmVyIChzcG9uc29yKVxuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsIC8vIERpZmZlcmVudCBmcm9tIHNlbmRlclxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTsgLy8gU2VuZGVyXG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpOyAvLyBHYXMgcGFpZCBieSBzcG9uc29yXG4gICAgICB0eEJ1aWxkZXIuaW5wdXRPYmplY3RzKGlucHV0T2JqZWN0cyk7IC8vIFJlcXVpcmVkIGZvciBzcG9uc29yZWQgdHhcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG5cbiAgICAgIC8vIFZlcmlmeSB0cmFuc2FjdGlvbiBzdHJ1Y3R1cmUgZm9yIHNwb25zb3JlZCB0cmFuc2FjdGlvblxuICAgICAgY29uc3QgcHJvZ3JhbW1hYmxlVHggPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eDtcbiAgICAgIHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9ucy5sZW5ndGguc2hvdWxkLmJlLmdyZWF0ZXJUaGFuKDApO1xuXG4gICAgICAvLyBWZXJpZnkgc3BvbnNvcmVkIHRyYW5zYWN0aW9uIGNoYXJhY3RlcmlzdGljc1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uc2VuZGVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzKTtcblxuICAgICAgLy8gU2hvdWxkIGhhdmUgdHJhbnNhY3Rpb25zIGZvciBtZXJnaW5nL3NwbGl0dGluZyBhbmQgdHJhbnNmZXJyaW5nIHdoZW4gdXNpbmcgaW5wdXRPYmplY3RzXG4gICAgICBwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnMubGVuZ3RoLnNob3VsZC5iZS5ncmVhdGVyVGhhbigwKTtcblxuICAgICAgLy8gVmVyaWZ5IHdlIGhhdmUgdHJhbnNmZXIgb3BlcmF0aW9ucyAodGhlIGV4YWN0IHN0cnVjdHVyZSB2YXJpZXMgd2l0aCBBUEkgdmVyc2lvbnMpXG4gICAgICBzaG91bGQuZXhpc3QocHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zKTtcblxuICAgICAgLy8gVmVyaWZ5IGlucHV0T2JqZWN0cyBhcmUgbm90IHVzZWQgaW4gZ2FzIHBheW1lbnQgKHRoZXkncmUgc2VwYXJhdGUpXG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLnBheW1lbnQuc2hvdWxkLm5vdC5jb250YWluRGVlcChpbnB1dE9iamVjdHMpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXhpc3QocmF3VHgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR5cGVvZiByYXdUeCwgJ3N0cmluZycpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHNwbGl0IGNvaW4gdHgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgY29uc3QgYW1vdW50ID0gMTAwMDAwMDAwMDtcbiAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSBuZXcgQXJyYXkoMTAwKS5maWxsKHsgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsIGFtb3VudDogYW1vdW50LnRvU3RyaW5nKCkgfSk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChyZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHRlc3REYXRhLmdhc0RhdGEpO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICAodHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj4pLnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudCEuc2hvdWxkLmRlZXBFcXVhbChcbiAgICAgICAgdGVzdERhdGEuY29pbnNHYXNQYXltZW50XG4gICAgICApO1xuXG4gICAgICB0eC5pbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHR4LmlucHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsXG4gICAgICAgIHZhbHVlOiAoYW1vdW50ICogMTAwKS50b1N0cmluZygpLFxuICAgICAgICBjb2luOiAndHN1aScsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxMDApO1xuICAgICAgdHgub3V0cHV0cy5mb3JFYWNoKChvdXRwdXQpID0+XG4gICAgICAgIG91dHB1dC5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgICBhZGRyZXNzOiB0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyxcbiAgICAgICAgICB2YWx1ZTogYW1vdW50LnRvU3RyaW5nKCksXG4gICAgICAgICAgY29pbjogJ3RzdWknLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzcGxpdCBjb2luIHR4IHdpdGggbW9yZSB0aGFuIDI1NSBpbnB1dCBvYmplY3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYW1vdW50ID0gMTAwMDAwMDAwMDtcbiAgICAgIGNvbnN0IG51bWJlck9mUmVjaXBpZW50cyA9IDEwO1xuICAgICAgY29uc3QgbnVtYmVyT2ZQYXltZW50T2JqZWN0cyA9IDEwMDA7XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG5cbiAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSBuZXcgQXJyYXkobnVtYmVyT2ZSZWNpcGllbnRzKS5maWxsKHtcbiAgICAgICAgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsXG4gICAgICAgIGFtb3VudDogYW1vdW50LnRvU3RyaW5nKCksXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgZ2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgcGF5bWVudDogdGVzdERhdGEuZ2VuZXJhdGVPYmplY3RzKG51bWJlck9mUGF5bWVudE9iamVjdHMpLFxuICAgICAgfTtcblxuICAgICAgdHhCdWlsZGVyLnNlbmQocmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShnYXNEYXRhKTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG5cbiAgICAgIGFzc2VydCh0eCBpbnN0YW5jZW9mIFN1aVRyYW5zYWN0aW9uKTtcbiAgICAgIHR4LnR5cGUuc2hvdWxkLmVxdWFsKFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICAgIHR4LmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHguaW5wdXRzWzBdLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBhZGRyZXNzOiB0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyxcbiAgICAgICAgdmFsdWU6IChhbW91bnQgKiAxMCkudG9TdHJpbmcoKSxcbiAgICAgICAgY29pbjogJ3RzdWknLFxuICAgICAgfSk7XG4gICAgICB0eC5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMTApO1xuICAgICAgdHgub3V0cHV0cy5mb3JFYWNoKChvdXRwdXQpID0+XG4gICAgICAgIG91dHB1dC5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgICBjb2luOiAndHN1aScsXG4gICAgICAgICAgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsXG4gICAgICAgICAgdmFsdWU6IGFtb3VudC50b1N0cmluZygpLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICAgIHR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKGdhc0RhdGEub3duZXIpO1xuICAgICAgdHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wcmljZS5zaG91bGQuZXF1YWwoZ2FzRGF0YS5wcmljZSk7XG4gICAgICB0eC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLmJ1ZGdldC5zaG91bGQuZXF1YWwoZ2FzRGF0YS5idWRnZXQpO1xuICAgICAgdHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoTUFYX0dBU19PQkpFQ1RTIC0gMSk7XG5cbiAgICAgIGNvbnN0IHByb2dyYW1tYWJsZVR4ID0gdHguc3VpVHJhbnNhY3Rpb24udHg7XG5cbiAgICAgIC8vIHRvdGFsIG9iamVjdHMgLSBvYmplY3RzIHNlbnQgYXMgZ2FzIHBheW1lbnQgKyBuby4gb2YgcmVjaXBpZW50IGFtb3VudHMocHVyZSlcbiAgICAgIC8vICsgbm8uIG9mIHVuaXF1ZSByZWNpcGllbnQgYWRkcmVzc2VzKGRlLWR1cGVkIG9iamVjdHMpXG4gICAgICBwcm9ncmFtbWFibGVUeC5pbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbChcbiAgICAgICAgbnVtYmVyT2ZQYXltZW50T2JqZWN0cyAtIChNQVhfR0FTX09CSkVDVFMgLSAxKSArIG51bWJlck9mUmVjaXBpZW50cyArIDFcbiAgICAgICk7XG4gICAgICBwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01lcmdlQ29pbnMnKTtcbiAgICAgIHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXS5zb3VyY2VzLmxlbmd0aC5zaG91bGQuZXF1YWwoTUFYX0NPTU1BTkRfQVJHUyAtIDEpO1xuICAgICAgcHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzFdLmtpbmQuc2hvdWxkLmVxdWFsKCdNZXJnZUNvaW5zJyk7XG4gICAgICBwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMV0uc291cmNlcy5sZW5ndGguc2hvdWxkLmVxdWFsKFxuICAgICAgICBudW1iZXJPZlBheW1lbnRPYmplY3RzIC0gKE1BWF9DT01NQU5EX0FSR1MgLSAxKSAtIChNQVhfR0FTX09CSkVDVFMgLSAxKVxuICAgICAgKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuICAgICAgcmVidWlsdFR4LnRvSnNvbigpLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKG51bWJlck9mUGF5bWVudE9iamVjdHMpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRmFpbCcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGZhaWwgZm9yIGludmFsaWQgc2VuZGVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5zZW5kZXIoJ3JhbmRvbVN0cmluZycpKS50aHJvd0Vycm9yKCdJbnZhbGlkIG9yIG1pc3Npbmcgc2VuZGVyLCBnb3Q6IHJhbmRvbVN0cmluZycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGZvciBpbnZhbGlkIHBheVR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5zZW5kKFt0ZXN0RGF0YS5pbnZhbGlkUmVjaXBpZW50c1swXV0pKS50aHJvd0Vycm9yKFxuICAgICAgICAnSW52YWxpZCBvciBtaXNzaW5nIGFkZHJlc3MsIGdvdDogcmFuZG9tU3RyaW5nJ1xuICAgICAgKTtcbiAgICAgIHNob3VsZCgoKSA9PiBidWlsZGVyLnNlbmQoW3Rlc3REYXRhLmludmFsaWRSZWNpcGllbnRzWzFdXSkpLnRocm93RXJyb3IoJ0ludmFsaWQgcmVjaXBpZW50IGFtb3VudCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGZvciBpbnZhbGlkIGdhc0RhdGEnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHNob3VsZCgoKSA9PiBidWlsZGVyLmdhc0RhdGEodGVzdERhdGEuaW52YWxpZEdhc093bmVyKSkudGhyb3dFcnJvcihcbiAgICAgICAgYEludmFsaWQgZ2FzIGFkZHJlc3MgJHt0ZXN0RGF0YS5pbnZhbGlkR2FzT3duZXIub3duZXJ9YFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBmb3IgaW52YWxpZCBnYXNCdWRnZXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHNob3VsZCgoKSA9PiBidWlsZGVyLmdhc0RhdGEodGVzdERhdGEuaW52YWxpZEdhc0J1ZGdldCkpLnRocm93RXJyb3IoJ0ludmFsaWQgZ2FzIGJ1ZGdldCAtMScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGZvciBpbnZhbGlkIGdhc1BheW1lbnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIGNvbnN0IGludmFsaWRHYXNQYXltZW50ID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsXG4gICAgICAgIHBheW1lbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBvYmplY3RJZDogJycsXG4gICAgICAgICAgICB2ZXJzaW9uOiAtMSxcbiAgICAgICAgICAgIGRpZ2VzdDogJycsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5nYXNEYXRhKGludmFsaWRHYXNQYXltZW50KSkudGhyb3dFcnJvcignSW52YWxpZCBwYXltZW50LCBpbnZhbGlkIG9yIG1pc3NpbmcgdmVyc2lvbicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGZvciBpbnZhbGlkIGlucHV0T2JqZWN0cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgY29uc3QgaW52YWxpZElucHV0T2JqZWN0cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIG9iamVjdElkOiAnJyxcbiAgICAgICAgICB2ZXJzaW9uOiAtMSxcbiAgICAgICAgICBkaWdlc3Q6ICcnLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIHNob3VsZCgoKSA9PiBidWlsZGVyLmlucHV0T2JqZWN0cyhpbnZhbGlkSW5wdXRPYmplY3RzKSkudGhyb3dFcnJvcihcbiAgICAgICAgJ0ludmFsaWQgaW5wdXQgb2JqZWN0LCBpbnZhbGlkIG9yIG1pc3NpbmcgdmVyc2lvbidcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIHRyYW5zZmVyIHdpdGggZGlmZmVyZW50IGdhcyBvd25lciBidXQgbm8gaW5wdXRPYmplY3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsIC8vIERpZmZlcmVudCBmcm9tIHNlbmRlclxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTsgLy8gU2VuZGVyXG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpOyAvLyBHYXMgcGFpZCBieSBzcG9uc29yXG4gICAgICAvLyBOb3RlOiBOT1QgcHJvdmlkaW5nIGlucHV0T2JqZWN0cyAtIHNob3VsZCBzdGlsbCB3b3JrIChmZWUgc3BvbnNvcnNoaXAgd2l0aG91dCBjb2luIHNwb25zb3JzaGlwKVxuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIHNob3VsZC5ub3QuZXhpc3Qoc3VpVHguc3VpVHJhbnNhY3Rpb24uaW5wdXRPYmplY3RzKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHRyYWN0IGlucHV0T2JqZWN0cyBmcm9tIHRyYW5zYWN0aW9uIGRhdGEgdmlhIHRvSnNvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGlucHV0T2JqZWN0cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIG9iamVjdElkOiAnMHgxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4JyxcbiAgICAgICAgICB2ZXJzaW9uOiAxMDAsXG4gICAgICAgICAgZGlnZXN0OiAnMkI4WEtRSjdtZnhRUFVXcUpKQUdqekJBeml2a1dLcTJjRWEzVzhMTHoxeUInLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLCAvLyBEaWZmZXJlbnQgZnJvbSBzZW5kZXJcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmlucHV0T2JqZWN0cyhpbnB1dE9iamVjdHMpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuXG4gICAgICAvLyBUZXN0IHRoYXQgdG9Kc29uIGV4dHJhY3RzIGlucHV0T2JqZWN0cyBmcm9tIHRyYW5zYWN0aW9uIHN0cnVjdHVyZVxuICAgICAgY29uc3QgdHhEYXRhID0gKHR4IGFzIGFueSkudG9Kc29uKCk7XG4gICAgICBzaG91bGQuZXhpc3QodHhEYXRhLmlucHV0T2JqZWN0cyk7XG5cbiAgICAgIC8vIFRoZSB0b0pzb24gc2hvdWxkIGV4dHJhY3QgdGhlIGlucHV0T2JqZWN0cyBmcm9tIHRoZSB0cmFuc2FjdGlvbiBzdHJ1Y3R1cmVcbiAgICAgIC8vIFRoaXMgdGVzdHMgb3VyIG5ldyBnZXRJbnB1dE9iamVjdHNGcm9tVHggbWV0aG9kXG4gICAgICBzaG91bGQuZXhpc3QodHhEYXRhLmlucHV0T2JqZWN0cyk7XG4gICAgICBBcnJheS5pc0FycmF5KHR4RGF0YS5pbnB1dE9iamVjdHMpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2Z1bmRzSW5BZGRyZXNzQmFsYW5jZScsICgpID0+IHtcbiAgICBjb25zdCBGVU5EU19JTl9BRERSRVNTX0JBTEFOQ0UgPSAnNTAwMDAwMDAwMCc7IC8vIDUgU1VJXG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIFBhdGggMmI6IHNlbGYtcGF5LCBhZGRyZXNzLWJhbGFuY2Ugb25seSDigJQgdXNlcyB3aXRoZHJhd2FsK3JlZGVlbV9mdW5kcywgbm90IFNwbGl0Q29pbnMoR2FzQ29pbiknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBSZWdyZXNzaW9uIGZvciBwcm9kdWN0aW9uIEluc3VmZmljaWVudENvaW5CYWxhbmNlIGZhaWx1cmVzIG9uIGNvbnNvbGlkYXRpb24uXG4gICAgICAvLyBXaXRoIHBheW1lbnQ9W10sIEdhc0NvaW4gb25seSBoYXMgZ2FzLWJ1ZGdldC13b3J0aCBvZiBiYWxhbmNlIGZvciBQVEIgb3BlcmF0aW9ucztcbiAgICAgIC8vIFNwbGl0Q29pbnMoR2FzQ29pbiwgW2xhcmdlX2Ftb3VudF0pIGFsd2F5cyBmYWlscyBhdCBjb21tYW5kIDAuXG4gICAgICAvLyBQYXRoIDJiIG11c3QgdXNlIHdpdGhkcmF3YWwrcmVkZWVtX2Z1bmRzIHRvIG1hdGVyaWFsaXNlIHRoZSBhZGRyZXNzIGJhbGFuY2UgYXMgYVxuICAgICAgLy8gY29pbiBvYmplY3QgYW5kIHNwbGl0IGZyb20gdGhhdCBjb2luIGluc3RlYWQuXG4gICAgICBjb25zdCBnYXNEYXRhTm9QYXltZW50ID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsXG4gICAgICAgIHBheW1lbnQ6IFtdLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpOyAvLyAyIHJlY2lwaWVudHNcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKGdhc0RhdGFOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShGVU5EU19JTl9BRERSRVNTX0JBTEFOQ0UpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICAvLyBQYXRoIDJiIFBUQiBjb21tYW5kIHNlcXVlbmNlICgyIHJlY2lwaWVudHMpOlxuICAgICAgLy8gICAwOiBNb3ZlQ2FsbChyZWRlZW1fZnVuZHMpICAgICAgICAgIOKAlCBtYXRlcmlhbGlzZSBhZGRyQ29pbiBmcm9tIGFkZHJlc3MgYmFsYW5jZVxuICAgICAgLy8gICAxOiBTcGxpdENvaW5zKGFkZHJDb2luLCBbYW1vdW50MF0pIOKAlCBzcGxpdCBmb3IgcmVjaXBpZW50IDBcbiAgICAgIC8vICAgMjogVHJhbnNmZXJPYmplY3RzICAgICAgICAgICAgICAgICDigJQgc2VuZCB0byByZWNpcGllbnQgMFxuICAgICAgLy8gICAzOiBTcGxpdENvaW5zKGFkZHJDb2luLCBbYW1vdW50MV0pIOKAlCBzcGxpdCBmb3IgcmVjaXBpZW50IDFcbiAgICAgIC8vICAgNDogVHJhbnNmZXJPYmplY3RzICAgICAgICAgICAgICAgICDigJQgc2VuZCB0byByZWNpcGllbnQgMVxuICAgICAgLy8gICA1OiBNZXJnZUNvaW5zKEdhc0NvaW4sIFthZGRyQ29pbl0pIOKAlCBkZXN0cm95IDAtYmFsYW5jZSBhZGRyQ29pbjsgZ2FzIGZyb20gYWNjdW11bGF0b3JcbiAgICAgIGNvbnN0IGNtZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG4gICAgICBjbWRzWzBdLmtpbmQuc2hvdWxkLmVxdWFsKCdNb3ZlQ2FsbCcsICdjb21tYW5kIDAgbXVzdCBiZSBNb3ZlQ2FsbChyZWRlZW1fZnVuZHMpJyk7XG4gICAgICBjbWRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICBjbWRzWzFdLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJywgJ2NvbW1hbmQgMSBtdXN0IGJlIFNwbGl0Q29pbnMoYWRkckNvaW4pJyk7XG4gICAgICBjbWRzWzJdLmtpbmQuc2hvdWxkLmVxdWFsKCdUcmFuc2Zlck9iamVjdHMnLCAnY29tbWFuZCAyIG11c3QgYmUgVHJhbnNmZXJPYmplY3RzJyk7XG4gICAgICBjbWRzWzNdLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJywgJ2NvbW1hbmQgMyBtdXN0IGJlIFNwbGl0Q29pbnMoYWRkckNvaW4pJyk7XG4gICAgICBjbWRzWzRdLmtpbmQuc2hvdWxkLmVxdWFsKCdUcmFuc2Zlck9iamVjdHMnLCAnY29tbWFuZCA0IG11c3QgYmUgVHJhbnNmZXJPYmplY3RzJyk7XG4gICAgICBjbWRzWzVdLmtpbmQuc2hvdWxkLmVxdWFsKCdNZXJnZUNvaW5zJywgJ2NvbW1hbmQgNSBtdXN0IGJlIE1lcmdlQ29pbnMoR2FzQ29pbiwgW2FkZHJDb2luXSknKTtcbiAgICAgIGNtZHMubGVuZ3RoLnNob3VsZC5lcXVhbCg2KTtcblxuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZnVuZHNJbkFkZHJlc3NCYWxhbmNlIS5zaG91bGQuZXF1YWwoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcblxuICAgICAgLy8gVHJhbnNhY3Rpb24gcGFyc2VyIG11c3QgY29ycmVjdGx5IGlkZW50aWZ5IHJlY2lwaWVudHMgZGVzcGl0ZSB0aGUgTW92ZUNhbGwgcHJlYW1ibGVcbiAgICAgIGNvbnN0IHBhcnNlZFJlY2lwaWVudHMgPSB1dGlscy5nZXRSZWNpcGllbnRzKHN1aVR4LnN1aVRyYW5zYWN0aW9uKTtcbiAgICAgIHBhcnNlZFJlY2lwaWVudHMubGVuZ3RoLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5yZWNpcGllbnRzLmxlbmd0aCk7XG4gICAgICBwYXJzZWRSZWNpcGllbnRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcyk7XG4gICAgICBwYXJzZWRSZWNpcGllbnRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwodGVzdERhdGEucmVjaXBpZW50c1swXS5hbW91bnQpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIC8vIFJvdW5kLXRyaXA6IHJlYnVpbHQgdHJhbnNhY3Rpb24gbXVzdCBiZSBiaXQtZm9yLWJpdCBpZGVudGljYWxcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgUGF0aCAyYiB3aXRoIGEgc2luZ2xlIHJlY2lwaWVudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IFNFTkRfQU1PVU5UID0gJzEyNzUxNzA5OTM3MTAnOyAvLyByZWFsaXN0aWMgY29uc29saWRhdGlvbiBhbW91bnQgKH4xMjc1IFNVSSlcbiAgICAgIGNvbnN0IEFERFJfQkFMID0gJzEyNzUxNzc1NDA5MTAnOyAvLyBmdW5kc0luQWRkcmVzc0JhbGFuY2UgPiBTRU5EX0FNT1VOVCArIGdhcyBidWRnZXRcbiAgICAgIGNvbnN0IGdhc0RhdGFOb1BheW1lbnQgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGFXaXRob3V0R2FzUGF5bWVudCxcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQoW3sgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLCBhbW91bnQ6IFNFTkRfQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKGdhc0RhdGFOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShBRERSX0JBTCk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgY29uc3QgY21kcyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LnRyYW5zYWN0aW9ucyBhcyBhbnlbXTtcblxuICAgICAgLy8gQ29tbWFuZCBzZXF1ZW5jZSBmb3IgMSByZWNpcGllbnQ6XG4gICAgICAvLyAgIDA6IE1vdmVDYWxsKHJlZGVlbV9mdW5kcylcbiAgICAgIC8vICAgMTogU3BsaXRDb2lucyhhZGRyQ29pbiwgW1NFTkRfQU1PVU5UXSlcbiAgICAgIC8vICAgMjogVHJhbnNmZXJPYmplY3RzXG4gICAgICAvLyAgIDM6IE1lcmdlQ29pbnMoR2FzQ29pbiwgW2FkZHJDb2luXSlcbiAgICAgIGNtZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJyk7XG4gICAgICBjbWRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICBjbWRzWzFdLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJyk7XG4gICAgICBjbWRzWzJdLmtpbmQuc2hvdWxkLmVxdWFsKCdUcmFuc2Zlck9iamVjdHMnKTtcbiAgICAgIGNtZHNbM10ua2luZC5zaG91bGQuZXF1YWwoJ01lcmdlQ29pbnMnLCAnZXhwZWN0ZWQgTWVyZ2VDb2lucyB0byBjb25zdW1lIDAtYmFsYW5jZSBhZGRyQ29pbicpO1xuICAgICAgY21kcy5sZW5ndGguc2hvdWxkLmVxdWFsKDQpO1xuXG4gICAgICBjb25zdCBwYXJzZWRSZWNpcGllbnRzID0gdXRpbHMuZ2V0UmVjaXBpZW50cyhzdWlUeC5zdWlUcmFuc2FjdGlvbik7XG4gICAgICBwYXJzZWRSZWNpcGllbnRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBwYXJzZWRSZWNpcGllbnRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcyk7XG4gICAgICBwYXJzZWRSZWNpcGllbnRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoU0VORF9BTU9VTlQpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgUGF0aCAyYiB3aXRoIFZhbGlkRHVyaW5nIGV4cGlyYXRpb24gKHByb2R1Y3Rpb24gY29uc29saWRhdGlvbiBzY2VuYXJpbyknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBNaXJyb3JzIHRoZSByZWFsIG9uLWNoYWluIGNvbnNvbGlkYXRpb24gdGhhdCBmYWlsZWQ6IGFkZHJlc3MgaW5kZXggMTAsIHdhbGxldFxuICAgICAgLy8gNjdmZTNmMTUuLi4sIHR4aWQgSkRibnlib3RnM2F4Zmp0QjUzTHJuVjFZdHZHTEZCVkc4bzJYejV4WDFtNlouXG4gICAgICAvLyBUaGUgcmVjb3ZlcigpIGNvZGUgc2V0cyBWYWxpZER1cmluZyB3aGVuIGNvaW5PYmplY3RzQmFsYW5jZT0wIGFuZFxuICAgICAgLy8gZnVuZHNJbkFkZHJlc3NCYWxhbmNlPjAgKENhc2UgMikuIFRoaXMgdGVzdCB2ZXJpZmllcyBib3RoIHRoZSBleHBpcmF0aW9uIHN1cnZpdmVzXG4gICAgICAvLyBzZXJpYWxpemF0aW9uIGFuZCB0aGUgUFRCIHVzZXMgUGF0aCAyYiAobm90IHRoZSBicm9rZW4gU3BsaXRDb2lucyhHYXNDb2luKSBwYXRoKS5cbiAgICAgIGNvbnN0IEdFTkVTSVNfQ0hBSU5fSUQgPSAnR0FGcENDY1JDeFRkRmZVRU1iUWJrTEJhWnkyUk5pR0FmdkZCaE1OcHEya1QnO1xuICAgICAgY29uc3QgU0VORF9BTU9VTlQgPSAnMTI3NTE3MDk5MzcxMCc7XG4gICAgICBjb25zdCBBRERSX0JBTCA9ICcxMjc1MTc3NTQwOTEwJztcbiAgICAgIGNvbnN0IGdhc0RhdGFOb1BheW1lbnQgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGFXaXRob3V0R2FzUGF5bWVudCxcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQoW3sgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLCBhbW91bnQ6IFNFTkRfQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKGdhc0RhdGFOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShBRERSX0JBTCk7XG4gICAgICB0eEJ1aWxkZXIuZXhwaXJhdGlvbih7XG4gICAgICAgIFZhbGlkRHVyaW5nOiB7XG4gICAgICAgICAgbWluRXBvY2g6IHsgU29tZTogMTE1NiB9LFxuICAgICAgICAgIG1heEVwb2NoOiB7IFNvbWU6IDExNTcgfSxcbiAgICAgICAgICBtaW5UaW1lc3RhbXA6IHsgTm9uZTogbnVsbCB9LFxuICAgICAgICAgIG1heFRpbWVzdGFtcDogeyBOb25lOiBudWxsIH0sXG4gICAgICAgICAgY2hhaW46IEdFTkVTSVNfQ0hBSU5fSUQsXG4gICAgICAgICAgbm9uY2U6IDEyMzQ1Njc4LFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIC8vIE11c3QgdXNlIFBhdGggMmIgKE1vdmVDYWxsIGZpcnN0KSwgbmV2ZXIgU3BsaXRDb2lucyhHYXNDb2luKSBmaXJzdFxuICAgICAgY29uc3QgY21kcyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LnRyYW5zYWN0aW9ucyBhcyBhbnlbXTtcbiAgICAgIGNtZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJywgJ1BhdGggMmIgbXVzdCBzdGFydCB3aXRoIE1vdmVDYWxsKHJlZGVlbV9mdW5kcyksIG5vdCBTcGxpdENvaW5zKEdhc0NvaW4pJyk7XG4gICAgICBjbWRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICBjbWRzW2NtZHMubGVuZ3RoIC0gMV0ua2luZC5zaG91bGQuZXF1YWwoXG4gICAgICAgICdNZXJnZUNvaW5zJyxcbiAgICAgICAgJ1BhdGggMmIgbXVzdCBlbmQgd2l0aCBNZXJnZUNvaW5zIHRvIGRlc3Ryb3kgMC1iYWxhbmNlIGFkZHJDb2luJ1xuICAgICAgKTtcblxuICAgICAgLy8gVmFsaWREdXJpbmcgZXhwaXJhdGlvbiBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXBcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcblxuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuXG4gICAgICBjb25zdCBleHBpcmF0aW9uID0gKHJlYnVpbHRUeC50b0pzb24oKS5leHBpcmF0aW9uIGFzIGFueSk/LlZhbGlkRHVyaW5nO1xuICAgICAgc2hvdWxkLmV4aXN0KGV4cGlyYXRpb24sICdWYWxpZER1cmluZyBleHBpcmF0aW9uIG11c3Qgc3Vydml2ZSByb3VuZC10cmlwJyk7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5taW5FcG9jaC5Tb21lKS5zaG91bGQuZXF1YWwoMTE1Nik7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5tYXhFcG9jaC5Tb21lKS5zaG91bGQuZXF1YWwoMTE1Nyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc2VsZi1wYXkgdHJhbnNmZXIgd2l0aCBjb2luIG9iamVjdHMgKyBhZGRyZXNzIGJhbGFuY2UgKFBhdGggMmMpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gUmVncmVzc2lvbiB0ZXN0IGZvciBDT0lOUy0zMzE6IHdoZW4gYm90aCBnYXNEYXRhLnBheW1lbnQgKGNvaW4gb2JqZWN0cykgYW5kXG4gICAgICAvLyBmdW5kc0luQWRkcmVzc0JhbGFuY2UgYXJlIHNldCwgU3VpIGRvZXMgTk9UIGF1dG9tYXRpY2FsbHkgbWVyZ2UgYWRkcmVzcyBiYWxhbmNlIGludG9cbiAgICAgIC8vIHRoZSBnYXMgY29pbi4gIFBhdGggMmMgbXVzdCBleHBsaWNpdGx5IGNhbGwgcmVkZWVtX2Z1bmRzICsgTWVyZ2VDb2lucyhnYXMsIFthZGRyQ29pbl0pXG4gICAgICAvLyBiZWZvcmUgU3BsaXRDb2lucyBzbyB0aGF0IHRoZSBnYXMgY29pbiBob2xkcyB0aGUgZnVsbCBzcGVuZGFibGUgYW1vdW50LlxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEodGVzdERhdGEuZ2FzRGF0YSk7IC8vIG5vbi1lbXB0eSBwYXltZW50IOKAlCB0cmlnZ2VycyBQYXRoIDJjXG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKEZVTkRTX0lOX0FERFJFU1NfQkFMQU5DRSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuXG4gICAgICAvLyBQYXRoIDJjIFBUQiBjb21tYW5kIHNlcXVlbmNlIChmb3IgMiByZWNpcGllbnRzKTpcbiAgICAgIC8vICAgMDogTW92ZUNhbGwocmVkZWVtX2Z1bmRzKSAgICAg4oCUIG1hdGVyaWFsaXplIGFkZHJDb2luIGZyb20gYWRkcmVzcyBiYWxhbmNlXG4gICAgICAvLyAgIDE6IE1lcmdlQ29pbnMoZ2FzLCBbYWRkckNvaW5dKeKAlCBnYXMgY29pbiA9IGNvaW5PYmplY3RzICsgYWRkckJhbCAoZnVsbCBzcGVuZGFibGUgYW1vdW50KVxuICAgICAgLy8gICAyOiBTcGxpdENvaW5zKGdhcykgICAgICAgICAgICDigJQgc3BsaXQgZm9yIHJlY2lwaWVudCAwXG4gICAgICAvLyAgIDM6IFRyYW5zZmVyT2JqZWN0cyAgICAgICAgICAgIOKAlCBzZW5kIHRvIHJlY2lwaWVudCAwXG4gICAgICAvLyAgIDQ6IFNwbGl0Q29pbnMoZ2FzKSAgICAgICAgICAgIOKAlCBzcGxpdCBmb3IgcmVjaXBpZW50IDFcbiAgICAgIC8vICAgNTogVHJhbnNmZXJPYmplY3RzICAgICAgICAgICAg4oCUIHNlbmQgdG8gcmVjaXBpZW50IDFcbiAgICAgIGNvbnN0IHByb2dyYW1tYWJsZVR4ID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHg7XG4gICAgICBjb25zdCBjbWRzID0gcHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zIGFzIGFueVtdO1xuICAgICAgY21kc1swXS5raW5kLnNob3VsZC5lcXVhbCgnTW92ZUNhbGwnLCAnY29tbWFuZCAwIG11c3QgYmUgTW92ZUNhbGwocmVkZWVtX2Z1bmRzKScpO1xuICAgICAgY21kc1swXS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgY21kc1sxXS5raW5kLnNob3VsZC5lcXVhbCgnTWVyZ2VDb2lucycsICdjb21tYW5kIDEgbXVzdCBiZSBNZXJnZUNvaW5zKGdhcywgW2FkZHJDb2luXSknKTtcbiAgICAgIGNtZHNbMl0ua2luZC5zaG91bGQuZXF1YWwoJ1NwbGl0Q29pbnMnLCAnY29tbWFuZCAyIG11c3QgYmUgU3BsaXRDb2lucyhnYXMsIFthbW91bnQwXSknKTtcbiAgICAgIGNtZHNbM10ua2luZC5zaG91bGQuZXF1YWwoJ1RyYW5zZmVyT2JqZWN0cycpO1xuICAgICAgY21kc1s0XS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycsICdjb21tYW5kIDQgbXVzdCBiZSBTcGxpdENvaW5zKGdhcywgW2Ftb3VudDFdKScpO1xuICAgICAgY21kc1s1XS5raW5kLnNob3VsZC5lcXVhbCgnVHJhbnNmZXJPYmplY3RzJyk7XG5cbiAgICAgIC8vIGZ1bmRzSW5BZGRyZXNzQmFsYW5jZSBtdXN0IGJlIHBlcnNpc3RlZCBpbiB0aGUgc2VyaWFsaXplZCB0cmFuc2FjdGlvblxuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZnVuZHNJbkFkZHJlc3NCYWxhbmNlIS5zaG91bGQuZXF1YWwoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICAvLyBSb3VuZC10cmlwOiByZWJ1aWx0IHRyYW5zYWN0aW9uIG11c3QgYmUgYml0LWZvci1iaXQgaWRlbnRpY2FsXG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc3BvbnNvcmVkIHRyYW5zZmVyIHdpdGggY29pbiBvYmplY3RzICsgYWRkcmVzcyBiYWxhbmNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW5wdXRPYmplY3RzID0gdGVzdERhdGEuZ2VuZXJhdGVPYmplY3RzKDIpO1xuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTtcbiAgICAgIHR4QnVpbGRlci5pbnB1dE9iamVjdHMoaW5wdXRPYmplY3RzKTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzKTtcblxuICAgICAgLy8gU3BvbnNvcmVkIHBhdGg6IE1vdmVDYWxsKHJlZGVlbV9mdW5kcykgKyBNZXJnZUNvaW5zICsgU3BsaXRDb2luc1xuICAgICAgY29uc3QgcHJvZ3JhbW1hYmxlVHggPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eDtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS5raW5kLnNob3VsZC5lcXVhbCgnTW92ZUNhbGwnKTtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1sxXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdNZXJnZUNvaW5zJyk7XG4gICAgICAocHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzJdIGFzIGFueSkua2luZC5zaG91bGQuZXF1YWwoJ1NwbGl0Q29pbnMnKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICAvLyBSb3VuZC10cmlwXG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc3BvbnNvcmVkIHRyYW5zZmVyIHdpdGggYWRkcmVzcyBiYWxhbmNlIG9ubHkgKG5vIGNvaW4gaW5wdXRPYmplY3RzKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoc3BvbnNvcmVkR2FzRGF0YSk7XG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKEZVTkRTX0lOX0FERFJFU1NfQkFMQU5DRSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICAvLyBQYXRoIDFiOiB3aXRoZHJhd2FsIOKGkiByZWRlZW1fZnVuZHMg4oaSIFNwbGl0Q29pbnMoYWRkckNvaW4pIOKGkiBUcmFuc2Zlck9iamVjdHNcbiAgICAgIC8vIFNwb25zb3IncyBnYXMgY29pbnMgcmVtYWluIGluIGdhc0RhdGEucGF5bWVudDsgdHguZ2FzIGlzIE5PVCB1c2VkIGZvciB0aGUgdHJhbnNmZXIgYW1vdW50LlxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MpO1xuICAgICAgY29uc3QgcHJvZ3JhbW1hYmxlVHggPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eDtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS5raW5kLnNob3VsZC5lcXVhbCgnTW92ZUNhbGwnKTtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1sxXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcblxuICAgICAgLy8gUm91bmQtdHJpcDogcmVidWlsZCBmcm9tIHJhd1xuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBQYXRoIDFiIHNlbmQtYWxsOiBzcG9uc29yZWQgYWRkci1iYWxhbmNlLW9ubHksIG5vIGNoYW5nZSAoTWVyZ2VDb2lucyBjb25zdW1lcyBhZGRyQ29pbiknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBSZXByb2R1Y2VzIHRoZSByZWFsIG9uLWNoYWluIGZhaWx1cmU6IFVudXNlZFZhbHVlV2l0aG91dERyb3AgeyByZXN1bHRfaWR4OiAwIH1cbiAgICAgIC8vIE9jY3VycyB3aGVuIHJlZGVlbV9mdW5kcyByZXR1cm5zIGFkZHJDb2luLCBTcGxpdENvaW5zIGRyYWlucyBpdCBjb21wbGV0ZWx5LCBhbmQgdGhlXG4gICAgICAvLyAwLWJhbGFuY2Ugc291cmNlIGNvaW4gaXMgbmV2ZXIgY29uc3VtZWQuICBGaXg6IE1lcmdlQ29pbnMoZ2FzLCBbYWRkckNvaW5dKSBhdCB0aGUgZW5kLlxuICAgICAgY29uc3QgU0VORF9BTU9VTlQgPSAnMTAwMDAwMCc7IC8vIDAuMDAxIFNVSSDigJQgc2FtZSBhcyB0aGUgZmFpbGluZyB0eFxuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQoW3sgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLCBhbW91bnQ6IFNFTkRfQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShTRU5EX0FNT1VOVCk7IC8vIHNlbmQtYWxsOiBiYWxhbmNlID09IHJlY2lwaWVudCBhbW91bnRcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBjb25zdCBjbWRzID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHgudHJhbnNhY3Rpb25zIGFzIGFueVtdO1xuXG4gICAgICAvLyBFeHBlY3RlZCBjb21tYW5kIHNlcXVlbmNlIGZvciBQYXRoIDFiIHNlbmQtYWxsOlxuICAgICAgLy8gICAwOiBNb3ZlQ2FsbCAocmVkZWVtX2Z1bmRzKSAgICAg4oCUIHdpdGhkcmF3IGFkZHJDb2luXG4gICAgICAvLyAgIDE6IFNwbGl0Q29pbnMoYWRkckNvaW4pICAgICAgICDigJQgc3BsaXQgcmVjaXBpZW50IGFtb3VudCBvZmYgYWRkckNvaW5cbiAgICAgIC8vICAgMjogVHJhbnNmZXJPYmplY3RzKFtzcGxpdF0pICAgIOKAlCBzZW5kIHRvIHJlY2lwaWVudFxuICAgICAgLy8gICAzOiBNZXJnZUNvaW5zKGdhcywgW2FkZHJDb2luXSkg4oCUIGNvbnN1bWUgdGhlIG5vdy16ZXJvLWJhbGFuY2UgYWRkckNvaW5cbiAgICAgIGNtZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJyk7XG4gICAgICBjbWRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICBjbWRzWzFdLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJyk7XG4gICAgICBjbWRzWzJdLmtpbmQuc2hvdWxkLmVxdWFsKCdUcmFuc2Zlck9iamVjdHMnKTtcbiAgICAgIGNtZHNbM10ua2luZC5zaG91bGQuZXF1YWwoJ01lcmdlQ29pbnMnLCAnZXhwZWN0ZWQgTWVyZ2VDb2lucyB0byBjb25zdW1lIDAtYmFsYW5jZSBhZGRyQ29pbiBhZnRlciBzZW5kLWFsbCcpO1xuXG4gICAgICAvLyBSZWNpcGllbnQgcGFyc2luZyBtdXN0IG5vdCBiZSBhZmZlY3RlZCBieSB0aGUgdHJhaWxpbmcgTWVyZ2VDb2luc1xuICAgICAgY29uc3QgcmVjaXBpZW50cyA9IHV0aWxzLmdldFJlY2lwaWVudHMoc3VpVHguc3VpVHJhbnNhY3Rpb24pO1xuICAgICAgcmVjaXBpZW50cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgcmVjaXBpZW50c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MpO1xuICAgICAgcmVjaXBpZW50c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKFNFTkRfQU1PVU5UKTtcblxuICAgICAgLy8gUm91bmQtdHJpcFxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBQYXRoIDFiIHdpdGggY2hhbmdlOiBzcG9uc29yZWQgYWRkci1iYWxhbmNlLW9ubHksIGV4Y2VzcyByZXR1cm5lZCB0byBzZW5kZXInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBmdW5kc0luQWRkcmVzc0JhbGFuY2UgZXhjZWVkcyB0aGUgdG90YWwgcmVjaXBpZW50IGFtb3VudCDihpIgY2hhbmdlIG11c3QgYmUgcmV0dXJuZWQgdG9cbiAgICAgIC8vIHRoZSBzZW5kZXIgYXMgYW4gZXh0cmEgVHJhbnNmZXJPYmplY3RzKFthZGRyQ29pbl0sIHNlbmRlcikuICBUaGUgdHJhbnNhY3Rpb24gcGFyc2VyIG11c3RcbiAgICAgIC8vIHNraXAgdGhpcyBjaGFuZ2UgdHJhbnNmZXIgYW5kIG9ubHkgcmVwb3J0IGFjdHVhbCByZWNpcGllbnRzLlxuICAgICAgY29uc3QgU0VORF9BTU9VTlQgPSAnMTAwJzsgLy8gZWFjaCBvZiB0aGUgdHdvIHRlc3REYXRhLnJlY2lwaWVudHMgZ2V0cyAxMDBcbiAgICAgIGNvbnN0IEVYQ0VTUyA9ICc5OTk5OTAwJzsgLy8gZnVuZHNJbkFkZHJlc3NCYWxhbmNlID0gMTBfMDAwXzAwMCwgdG90YWwgc2VuZCA9IDIwMFxuICAgICAgY29uc3QgRlVORFNfQkFMQU5DRSA9IChOdW1iZXIoU0VORF9BTU9VTlQpICogdGVzdERhdGEucmVjaXBpZW50cy5sZW5ndGggKyBOdW1iZXIoRVhDRVNTKSkudG9TdHJpbmcoKTtcblxuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7IC8vIDIgcmVjaXBpZW50cyDDlyAxMDAgTUlTVCA9IDIwMCBNSVNUIHRvdGFsXG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfQkFMQU5DRSk7IC8vIDEwXzAwMF8wMDAgPiAyMDAg4oaSIGhhcyBjaGFuZ2VcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBjb25zdCBjbWRzID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHgudHJhbnNhY3Rpb25zIGFzIGFueVtdO1xuXG4gICAgICAvLyBFeHBlY3RlZCBzZXF1ZW5jZSBmb3IgUGF0aCAxYiB3aXRoIGNoYW5nZSAoMiByZWNpcGllbnRzKTpcbiAgICAgIC8vICAgMDogTW92ZUNhbGwgKHJlZGVlbV9mdW5kcylcbiAgICAgIC8vICAgMTogU3BsaXRDb2lucyAg4oCUICByZWNpcGllbnQgMFxuICAgICAgLy8gICAyOiBUcmFuc2Zlck9iamVjdHMgIOKAlCAgcmVjaXBpZW50IDBcbiAgICAgIC8vICAgMzogU3BsaXRDb2lucyAg4oCUICByZWNpcGllbnQgMVxuICAgICAgLy8gICA0OiBUcmFuc2Zlck9iamVjdHMgIOKAlCAgcmVjaXBpZW50IDFcbiAgICAgIC8vICAgNTogVHJhbnNmZXJPYmplY3RzKFthZGRyQ29pbl0sIHNlbmRlcikgIOKAlCAgY2hhbmdlIGJhY2sgdG8gc2VuZGVyXG4gICAgICBjbWRzWzBdLmtpbmQuc2hvdWxkLmVxdWFsKCdNb3ZlQ2FsbCcpO1xuICAgICAgY21kc1swXS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgY29uc3QgbGFzdENtZCA9IGNtZHNbY21kcy5sZW5ndGggLSAxXTtcbiAgICAgIGxhc3RDbWQua2luZC5zaG91bGQuZXF1YWwoJ1RyYW5zZmVyT2JqZWN0cycsICdsYXN0IGNvbW1hbmQgbXVzdCBiZSB0aGUgY2hhbmdlIHRyYW5zZmVyJyk7XG5cbiAgICAgIC8vIFRoZSBsYXN0IFRyYW5zZmVyT2JqZWN0cyByZXR1cm5zIGNoYW5nZSB0byB0aGUgKnNlbmRlciosIG5vdCBhIHJlY2lwaWVudFxuICAgICAgY29uc3QgY2hhbmdlQWRkcklucHV0ID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHguaW5wdXRzW2xhc3RDbWQuYWRkcmVzcy5pbmRleF0gYXMgYW55O1xuICAgICAgY29uc3QgY2hhbmdlQWRkciA9IHV0aWxzLmdldEFkZHJlc3MoY2hhbmdlQWRkcklucHV0KTtcbiAgICAgIGNoYW5nZUFkZHIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLCAnY2hhbmdlIG11c3QgZ28gYmFjayB0byBzZW5kZXInKTtcblxuICAgICAgLy8gUGFyc2VyIG11c3QgcmV0dXJuIG9ubHkgdGhlIGFjdHVhbCByZWNpcGllbnRzLCBub3QgdGhlIGNoYW5nZSB0cmFuc2ZlclxuICAgICAgY29uc3QgcmVjaXBpZW50cyA9IHV0aWxzLmdldFJlY2lwaWVudHMoc3VpVHguc3VpVHJhbnNhY3Rpb24pO1xuICAgICAgcmVjaXBpZW50cy5sZW5ndGguc2hvdWxkLmVxdWFsKHRlc3REYXRhLnJlY2lwaWVudHMubGVuZ3RoKTtcbiAgICAgIHJlY2lwaWVudHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwodGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzKTtcbiAgICAgIHJlY2lwaWVudHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbChTRU5EX0FNT1VOVCk7XG4gICAgICByZWNpcGllbnRzWzFdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKHRlc3REYXRhLnJlY2lwaWVudHNbMV0uYWRkcmVzcyk7XG4gICAgICByZWNpcGllbnRzWzFdLmFtb3VudC5zaG91bGQuZXF1YWwoU0VORF9BTU9VTlQpO1xuXG4gICAgICAvLyBSb3VuZC10cmlwXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc3BvbnNvcmVkIHR4IGdhcyBwYWlkIGZyb20gc3BvbnNvciBhZGRyZXNzIGJhbGFuY2UgKGVtcHR5IHBheW1lbnQpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW5wdXRPYmplY3RzID0gdGVzdERhdGEuZ2VuZXJhdGVPYmplY3RzKDEpO1xuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YU5vUGF5bWVudCA9IHtcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLFxuICAgICAgICBwcmljZTogdGVzdERhdGEuZ2FzRGF0YS5wcmljZSxcbiAgICAgICAgYnVkZ2V0OiB0ZXN0RGF0YS5nYXNEYXRhLmJ1ZGdldCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGFOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmlucHV0T2JqZWN0cyhpbnB1dE9iamVjdHMpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MpO1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIC8vIFNwb25zb3JlZCBwYXRoIHdpdGggY29pbiBvYmplY3RzLCBubyBhZGRyZXNzIGJhbGFuY2Ugd2l0aGRyYXdhbFxuICAgICAgY29uc3QgcHJvZ3JhbW1hYmxlVHggPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eDtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJvdW5kLXRyaXAgYSBzZWxmLXBheSB0cmFuc2ZlciB3aXRoIEVwb2NoIGV4cGlyYXRpb24gdmlhIGZyb21CeXRlcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFJlZ3Jlc3Npb24gdGVzdCBmb3IgdGhlIEJpZ0ludCByb3VuZC10cmlwIGJ1ZzpcbiAgICAgIC8vIEJDUy5VNjQgZGVzZXJpYWxpemVzIHU2NCBhcyBCaWdJbnQsIGJ1dCB0aGUgcHJldmlvdXMgc3VwZXJzdHJ1Y3Qgc2NoZW1hIHVzZWQgaW50ZWdlcigpXG4gICAgICAvLyB3aGljaCByZWplY3RlZCBCaWdJbnQsIGNhdXNpbmcgZnJvbUJ5dGVzKCkgdG8gdGhyb3cgYSBTdHJ1Y3RFcnJvciBhdCBcImV4cGlyYXRpb25cIi5cbiAgICAgIC8vIFN0cmluZ0VuY29kZWRCaWdpbnQgbm93IGFjY2VwdHMgc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50LCBmaXhpbmcgdGhlIHJvdW5kLXRyaXAuXG4gICAgICBjb25zdCBnYXNEYXRhTm9QYXltZW50ID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsXG4gICAgICAgIHBheW1lbnQ6IFtdLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoZ2FzRGF0YU5vUGF5bWVudCk7XG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKEZVTkRTX0lOX0FERFJFU1NfQkFMQU5DRSk7XG4gICAgICB0eEJ1aWxkZXIuZXhwaXJhdGlvbih7IEVwb2NoOiAzMjQgfSk7IC8vIG51bWJlciBpbnB1dFxuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICAvLyBmcm9tQnl0ZXMgbXVzdCBub3QgdGhyb3cgU3RydWN0RXJyb3Ig4oCUIHRoaXMgd2FzIHRoZSBmYWlsaW5nIGNhc2UgYmVmb3JlIHRoZSBmaXhcbiAgICAgIHNob3VsZC5kb2VzTm90VGhyb3coKCkgPT4ge1xuICAgICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgICBzaG91bGQuZXhpc3QocmVidWlsZGVyKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBGdWxsIHJvdW5kLXRyaXA6IHJlYnVpbHQgdHggbXVzdCBzZXJpYWxpemUgaWRlbnRpY2FsbHlcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcblxuICAgICAgLy8gRXBvY2ggdmFsdWUgbXVzdCBzdXJ2aXZlIHRoZSByb3VuZC10cmlwIHJlZ2FyZGxlc3Mgb2YgQmlnSW50L251bWJlciByZXByZXNlbnRhdGlvblxuICAgICAgY29uc3QgcmVidWlsdEpzb24gPSByZWJ1aWx0VHgudG9Kc29uKCk7XG4gICAgICBjb25zdCBlcG9jaFZhbCA9IChyZWJ1aWx0SnNvbi5leHBpcmF0aW9uIGFzIGFueSk/LkVwb2NoO1xuICAgICAgc2hvdWxkLmV4aXN0KGVwb2NoVmFsKTtcbiAgICAgIE51bWJlcihlcG9jaFZhbCkuc2hvdWxkLmVxdWFsKDMyNCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJvdW5kLXRyaXAgYSBzZWxmLXBheSB0cmFuc2ZlciB3aXRoIFZhbGlkRHVyaW5nIGV4cGlyYXRpb24gdmlhIGZyb21CeXRlcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFZlcmlmaWVzIHRoZSBmdWxsIDYtZmllbGQgVmFsaWREdXJpbmdFeHBpcmF0aW9uIEJDUyBzY2hlbWE6XG4gICAgICAvLyAgIG1pbkVwb2NoL21heEVwb2NoIGFzIE9wdGlvbjx1NjQ+LCBtaW5UaW1lc3RhbXAvbWF4VGltZXN0YW1wIGFzIE9wdGlvbjx1NjQ+IChOb25lKSxcbiAgICAgIC8vICAgY2hhaW4gYXMgMzItYnl0ZSBCYXNlNTggT2JqZWN0RGlnZXN0LCBub25jZSBhcyB1MzIuXG4gICAgICAvLyBVc2VzIGEgcmVhbCBtYWlubmV0IGdlbmVzaXMgY2hlY2twb2ludCBkaWdlc3QgKDMyIGJ5dGVzLCBCYXNlNTgpLlxuICAgICAgY29uc3QgR0VORVNJU19DSEFJTl9JRCA9ICdHQUZwQ0NjUkN4VGRGZlVFTWJRYmtMQmFaeTJSTmlHQWZ2RkJoTU5wcTJrVCc7XG4gICAgICBjb25zdCBGVU5EU19JTl9BRERSRVNTX0JBTEFOQ0UgPSAnNTAwMDAwMDAwMCc7XG4gICAgICBjb25zdCBnYXNEYXRhTm9QYXltZW50ID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsXG4gICAgICAgIHBheW1lbnQ6IFtdLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoZ2FzRGF0YU5vUGF5bWVudCk7XG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKEZVTkRTX0lOX0FERFJFU1NfQkFMQU5DRSk7XG4gICAgICB0eEJ1aWxkZXIuZXhwaXJhdGlvbih7XG4gICAgICAgIFZhbGlkRHVyaW5nOiB7XG4gICAgICAgICAgbWluRXBvY2g6IHsgU29tZTogNTAwIH0sXG4gICAgICAgICAgbWF4RXBvY2g6IHsgU29tZTogNTAxIH0sXG4gICAgICAgICAgbWluVGltZXN0YW1wOiB7IE5vbmU6IG51bGwgfSxcbiAgICAgICAgICBtYXhUaW1lc3RhbXA6IHsgTm9uZTogbnVsbCB9LFxuICAgICAgICAgIGNoYWluOiBHRU5FU0lTX0NIQUlOX0lELFxuICAgICAgICAgIG5vbmNlOiAweGRlYWRiZWVmLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIC8vIGZyb21CeXRlcyBtdXN0IG5vdCB0aHJvdyDigJQgVmFsaWREdXJpbmcgZmllbGRzIG11c3Qgc3Vydml2ZSBkZXNlcmlhbGl6YXRpb25cbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuXG4gICAgICAvLyBCQ1Mgcm91bmQtdHJpcDogc2VyaWFsaXplZCBieXRlcyBtdXN0IGJlIGlkZW50aWNhbFxuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcblxuICAgICAgLy8gQWxsIFZhbGlkRHVyaW5nIGZpZWxkcyBtdXN0IHN1cnZpdmUgdGhlIHJvdW5kLXRyaXBcbiAgICAgIGNvbnN0IGV4cGlyYXRpb24gPSAocmVidWlsdFR4LnRvSnNvbigpLmV4cGlyYXRpb24gYXMgYW55KT8uVmFsaWREdXJpbmc7XG4gICAgICBzaG91bGQuZXhpc3QoZXhwaXJhdGlvbik7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5taW5FcG9jaD8uU29tZSA/PyBleHBpcmF0aW9uLm1pbkVwb2NoKS5zaG91bGQuZXF1YWwoNTAwKTtcbiAgICAgIE51bWJlcihleHBpcmF0aW9uLm1heEVwb2NoPy5Tb21lID8/IGV4cGlyYXRpb24ubWF4RXBvY2gpLnNob3VsZC5lcXVhbCg1MDEpO1xuICAgICAgZXhwaXJhdGlvbi5jaGFpbi5zaG91bGQuZXF1YWwoR0VORVNJU19DSEFJTl9JRCk7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5ub25jZSkuc2hvdWxkLmVxdWFsKDB4ZGVhZGJlZWYpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnbGFyZ2UgYW1vdW50cyBleGNlZWRpbmcgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVInLCAoKSA9PiB7XG4gICAgLy8gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIgPSA5MDA3MTk5MjU0NzQwOTkxLlxuICAgIC8vIFVzaW5nIE51bWJlcigpIGZvciBhbW91bnRzIGFib3ZlIHRoaXMgc2lsZW50bHkgcm91bmRzIHRvIHRoZSBuZWFyZXN0IHJlcHJlc2VudGFibGUgZmxvYXQuXG4gICAgLy8gOTAwNzE5OTI1NDc0MDk5MyAoTUFYX1NBRkVfSU5URUdFUiArIDIpIGlzIE5PVCBleGFjdGx5IHJlcHJlc2VudGFibGUgYXMgYSBKUyBOdW1iZXIg4oCUIGl0XG4gICAgLy8gcm91bmRzIGRvd24gdG8gOTAwNzE5OTI1NDc0MDk5MiDigJQgc28gQkNTIHdvdWxkIGVuY29kZSB0aGUgd3JvbmcgdmFsdWUuXG4gICAgLy8gQmlnSW50IHByZXNlcnZlcyB0aGUgZXhhY3QgdmFsdWUgYW5kIGlzIHRoZSBjb3JyZWN0IHR5cGUgZm9yIEJDUyB1NjQgZW5jb2RpbmcuXG4gICAgLy9cbiAgICAvLyBUaGUgY29yZSBjaGVjayBpbiBlYWNoIHRlc3QgaXMgdHgub3V0cHV0c1swXS52YWx1ZSA9PT0gTEFSR0VfQU1PVU5UOiB0aGlzIHJlYWRzIGZyb20gdGhlXG4gICAgLy8gaW4tbWVtb3J5IGJ1aWxkZXIgc3RhdGUgKGEgQmlnSW50LCBub3QgQkNTLWRlY29kZWQpLCBzbyBpdCBhY2N1cmF0ZWx5IGRpc3Rpbmd1aXNoZXNcbiAgICAvLyBCaWdJbnQoKSB2cyBOdW1iZXIoKSBlbmNvZGluZyBhdCBidWlsZCB0aW1lLlxuICAgIGNvbnN0IExBUkdFX0FNT1VOVCA9ICc5MDA3MTk5MjU0NzQwOTkzJzsgLy8gTUFYX1NBRkVfSU5URUdFUiArIDJcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzZWxmLXBheSB0cmFuc2ZlciAoUGF0aCAyKSB3aXRoIGFtb3VudCA+IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSIGFuZCBlbmNvZGUgaXQgcHJlY2lzZWx5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKFt7IGFkZHJlc3M6IHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcywgYW1vdW50OiBMQVJHRV9BTU9VTlQgfV0pO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEodGVzdERhdGEuZ2FzRGF0YSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICAvLyBXaXRoIE51bWJlcigpIHRoZSBhbW91bnQgd291bGQgYmUgc2lsZW50bHkgcm91bmRlZCB0byA5MDA3MTk5MjU0NzQwOTkyIOKAlCBCaWdJbnQgcHJlc2VydmVzIHRoZSBleGFjdCB2YWx1ZVxuICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHgub3V0cHV0c1swXS52YWx1ZS5zaG91bGQuZXF1YWwoTEFSR0VfQU1PVU5UKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHNwb25zb3JlZCB0cmFuc2ZlciB3aXRoIGNvaW4gb2JqZWN0cyAoUGF0aCAxYSkgd2l0aCBhbW91bnQgPiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiBhbmQgZW5jb2RlIGl0IHByZWNpc2VseScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGlucHV0T2JqZWN0cyA9IHRlc3REYXRhLmdlbmVyYXRlT2JqZWN0cygyKTtcbiAgICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKFt7IGFkZHJlc3M6IHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcywgYW1vdW50OiBMQVJHRV9BTU9VTlQgfV0pO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoc3BvbnNvcmVkR2FzRGF0YSk7XG4gICAgICB0eEJ1aWxkZXIuaW5wdXRPYmplY3RzKGlucHV0T2JqZWN0cyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICAvLyBXaXRoIE51bWJlcigpIHRoZSBhbW91bnQgd291bGQgYmUgc2lsZW50bHkgcm91bmRlZCB0byA5MDA3MTk5MjU0NzQwOTkyIOKAlCBCaWdJbnQgcHJlc2VydmVzIHRoZSBleGFjdCB2YWx1ZVxuICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHgub3V0cHV0c1swXS52YWx1ZS5zaG91bGQuZXF1YWwoTEFSR0VfQU1PVU5UKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHNwb25zb3JlZCBhZGRyLWJhbGFuY2Utb25seSB0cmFuc2ZlciAoUGF0aCAxYikgd2l0aCBhbW91bnQgPiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiBhbmQgcm91bmQtdHJpcCBjb3JyZWN0bHknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgICBvd25lcjogdGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiB0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MsIGFtb3VudDogTEFSR0VfQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShMQVJHRV9BTU9VTlQpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgLy8gV2l0aCBOdW1iZXIoKSB0aGUgYW1vdW50IHdvdWxkIGJlIHNpbGVudGx5IHJvdW5kZWQgdG8gOTAwNzE5OTI1NDc0MDk5MiDigJQgQmlnSW50IHByZXNlcnZlcyB0aGUgZXhhY3QgdmFsdWVcbiAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHR4Lm91dHB1dHNbMF0udmFsdWUuc2hvdWxkLmVxdWFsKExBUkdFX0FNT1VOVCk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcblxuICAgICAgLy8gRnVsbCByb3VuZC10cmlwOiByZWJ1aWxkaW5nIGZyb20gQkNTIGJ5dGVzIG11c3QgcHJvZHVjZSBpZGVudGljYWwgYnl0ZXNcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcblxuICAgICAgY29uc3QgcmVjaXBpZW50cyA9IHV0aWxzLmdldFJlY2lwaWVudHMoXG4gICAgICAgIChyZWJ1aWx0VHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj4pLnN1aVRyYW5zYWN0aW9uXG4gICAgICApO1xuICAgICAgcmVjaXBpZW50c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKExBUkdFX0FNT1VOVCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdwcm9kIGFkZHJlc3MgYmFsYW5jZSBjb25zb2xpZGF0aW9uIChDRUNITy0xMjEwKScsICgpID0+IHtcbiAgICAvLyBGYWlsZWQgcHJvZCBjb25zb2xpZGF0aW9uIDZhMTljYjhiY2Q0NzUxZGJkODkxYTcyMmVlMDRlNTUyICh0eFJlcXVlc3QgZWU1ZDYwZDctZmE1My00ZmE0LWFkY2YtMjY0MzVjOTMxN2JmKS5cbiAgICAvLyBCcm9hZGNhc3QgZmFpbGVkIHdpdGggc3RhbGUgY29pbiBvYmplY3QgdmVyc2lvbjsgdGhlIGFtb3VudCBtdXN0IHN0aWxsIGVuY29kZSBsb3NzbGVzc2x5LlxuICAgIGNvbnN0IENPTlNPTElEQVRJT05fQU1PVU5UID0gJzE4NTM2Nzk3ODQyNjEzNzAwJzsgLy8gfjE4LjVNIFNVSSBpbiBNSVNUIChzZW5kQWNjb3VudGluZy5hbW91bnRTdHJpbmcpXG4gICAgY29uc3QgQ09OU09MSURBVElPTl9TRU5ERVIgPSAnMHg0NmE1M2UyNzEyNTYxZjRlMGQ4MjcyYmQyN2EzOTZiNmJmOTMyNWY5MmYzNGI5NDkwNDFiODc4M2Q1NzQ2OWRkJztcbiAgICBjb25zdCBDT05TT0xJREFUSU9OX1JFQ0lQSUVOVCA9ICcweDNkYTJjYjY3Yzg4N2M5YTAzZDEwNTJkNDg2NzMzYTc3MTA1ODI0Zjc0MTNmYzNjYmJlMzY0MWQ0YjY3YWYxMDInO1xuXG4gICAgaXQoJ3Nob3VsZCBhY2NlcHQgdGhlIHByb2QgY29uc29saWRhdGlvbiBhbW91bnQgaW4gaXNWYWxpZEFtb3VudCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHV0aWxzLmlzVmFsaWRBbW91bnQoQ09OU09MSURBVElPTl9BTU9VTlQpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICBOdW1iZXIuaXNTYWZlSW50ZWdlcihOdW1iZXIoQ09OU09MSURBVElPTl9BTU9VTlQpKS5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYWRkcmVzcy1iYWxhbmNlLW9ubHkgY29uc29saWRhdGlvbiB3aXRoIGV4YWN0IHByb2QgYW1vdW50IChQYXRoIDIsIGVtcHR5IHBheW1lbnQpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZ2FzRGF0YU5vUGF5bWVudCA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YVdpdGhvdXRHYXNQYXltZW50LFxuICAgICAgICBwYXltZW50OiBbXSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcihDT05TT0xJREFUSU9OX1NFTkRFUik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiBDT05TT0xJREFUSU9OX1JFQ0lQSUVOVCwgYW1vdW50OiBDT05TT0xJREFUSU9OX0FNT1VOVCB9XSk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShnYXNEYXRhTm9QYXltZW50KTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoQ09OU09MSURBVElPTl9BTU9VTlQpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHgub3V0cHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogQ09OU09MSURBVElPTl9SRUNJUElFTlQsXG4gICAgICAgIHZhbHVlOiBDT05TT0xJREFUSU9OX0FNT1VOVCxcbiAgICAgICAgY29pbjogJ3RzdWknLFxuICAgICAgfSk7XG4gICAgICB0eC5pbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHR4LmlucHV0c1swXS52YWx1ZS5zaG91bGQuZXF1YWwoQ09OU09MSURBVElPTl9BTU9VTlQpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IFN1aVRyYW5zYWN0aW9uLmRlc2VyaWFsaXplU3VpVHJhbnNhY3Rpb24ocmF3VHgpO1xuICAgICAgY29uc3QgcmVjaXBpZW50cyA9IHV0aWxzLmdldFJlY2lwaWVudHMoZGVzZXJpYWxpemVkKTtcbiAgICAgIHJlY2lwaWVudHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHJlY2lwaWVudHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoQ09OU09MSURBVElPTl9SRUNJUElFTlQpO1xuICAgICAgcmVjaXBpZW50c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKENPTlNPTElEQVRJT05fQU1PVU5UKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYWRkcmVzcy1iYWxhbmNlIGNvbnNvbGlkYXRpb24gd2l0aCBjb2luIG9iamVjdHMgYW5kIGV4YWN0IHByb2QgYW1vdW50IChQYXRoIDIpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gUHJvZCBmYWlsdXJlIHJlZmVyZW5jZWQgc3RhbGUgZ2FzL2NvaW4gb2JqZWN0IHZlcnNpb25zIGJldHdlZW4gc2lnbiBhbmQgYnJvYWRjYXN0LlxuICAgICAgLy8gQnVpbGRlciBtdXN0IHN0aWxsIGVuY29kZSB0aGUgZnVsbCBjb25zb2xpZGF0aW9uIGFtb3VudCBpbiBTcGxpdENvaW5zLlxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKENPTlNPTElEQVRJT05fU0VOREVSKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKFt7IGFkZHJlc3M6IENPTlNPTElEQVRJT05fUkVDSVBJRU5ULCBhbW91bnQ6IENPTlNPTElEQVRJT05fQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHsgLi4udGVzdERhdGEuZ2FzRGF0YSwgb3duZXI6IENPTlNPTElEQVRJT05fU0VOREVSIH0pO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShDT05TT0xJREFUSU9OX0FNT1VOVCk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICB0eC5vdXRwdXRzWzBdLnZhbHVlLnNob3VsZC5lcXVhbChDT05TT0xJREFUSU9OX0FNT1VOVCk7XG4gICAgICB0eC5pbnB1dHNbMF0udmFsdWUuc2hvdWxkLmVxdWFsKENPTlNPTElEQVRJT05fQU1PVU5UKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG5cbiAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSB1dGlscy5nZXRSZWNpcGllbnRzKFxuICAgICAgICAocmVidWlsdFR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+KS5zdWlUcmFuc2FjdGlvblxuICAgICAgKTtcbiAgICAgIHJlY2lwaWVudHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoQ09OU09MSURBVElPTl9SRUNJUElFTlQpO1xuICAgICAgcmVjaXBpZW50c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKENPTlNPTElEQVRJT05fQU1PVU5UKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0JhbGFuY2VXaXRoZHJhd2FsIEJDUyBlbmNvZGluZyAoRnVuZHNXaXRoZHJhd2FsIGZvcm1hdCknLCAoKSA9PiB7XG4gICAgY29uc3QgQU1PVU5UID0gJzEwMDAwMDAwMCc7IC8vIDAuMSBTVUkgaW4gTUlTVFxuICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgfTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIGJ1aWxkU3BvbnNvcmVkVHhXaXRoQWRkcmVzc0JhbGFuY2UoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQoW3sgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLCBhbW91bnQ6IEFNT1VOVCB9XSk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoQU1PVU5UKTtcbiAgICAgIHJldHVybiB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICB9XG5cbiAgICBpdCgnc2hvdWxkIGVuY29kZSBCYWxhbmNlV2l0aGRyYXdhbCBpbnB1dCB3aXRoIEZ1bmRzV2l0aGRyYXdhbCBzdHJ1Y3R1cmUgKHJlc2VydmF0aW9uL3R5cGVBcmcvd2l0aGRyYXdGcm9tKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgYnVpbGRTcG9uc29yZWRUeFdpdGhBZGRyZXNzQmFsYW5jZSgpO1xuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIGNvbnN0IGlucHV0cyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LmlucHV0cyBhcyBhbnlbXTtcblxuICAgICAgY29uc3QgYndJbnB1dCA9IGlucHV0cy5maW5kKFxuICAgICAgICAoaW5wKSA9PiBpbnA/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWQgfHwgaW5wPy52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICAgIHNob3VsZC5leGlzdChid0lucHV0LCAnQmFsYW5jZVdpdGhkcmF3YWwgaW5wdXQgbXVzdCBiZSBwcmVzZW50Jyk7XG5cbiAgICAgIGNvbnN0IGJ3ID0gYndJbnB1dC5CYWxhbmNlV2l0aGRyYXdhbCA/PyBid0lucHV0LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbDtcblxuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnJlc2VydmF0aW9uLCAncmVzZXJ2YXRpb24gZmllbGQgbXVzdCBleGlzdCcpO1xuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnJlc2VydmF0aW9uLk1heEFtb3VudFU2NCwgJ3Jlc2VydmF0aW9uLk1heEFtb3VudFU2NCBtdXN0IGV4aXN0Jyk7XG4gICAgICBidy5yZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQudG9TdHJpbmcoKS5zaG91bGQuZXF1YWwoQU1PVU5UKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnR5cGVBcmcsICd0eXBlQXJnIGZpZWxkIG11c3QgZXhpc3QnKTtcbiAgICAgIHNob3VsZC5leGlzdChidy50eXBlQXJnLkJhbGFuY2UsICd0eXBlQXJnLkJhbGFuY2UgbXVzdCBleGlzdCcpO1xuXG4gICAgICBzaG91bGQuZXhpc3QoYncud2l0aGRyYXdGcm9tLCAnd2l0aGRyYXdGcm9tIGZpZWxkIG11c3QgZXhpc3QnKTtcbiAgICAgIHNob3VsZC5leGlzdChcbiAgICAgICAgYncud2l0aGRyYXdGcm9tLlNlbmRlciAhPT0gdW5kZWZpbmVkIHx8IGJ3LndpdGhkcmF3RnJvbS5TcG9uc29yICE9PSB1bmRlZmluZWQsXG4gICAgICAgICd3aXRoZHJhd0Zyb20gbXVzdCBiZSBTZW5kZXIgb3IgU3BvbnNvcidcbiAgICAgICk7XG5cbiAgICAgIC8vIE9sZCBmb3JtYXQgZmllbGRzIG11c3QgTk9UIGV4aXN0IGRpcmVjdGx5IG9uIGJ3XG4gICAgICBzaG91bGQubm90LmV4aXN0KGJ3LmFtb3VudCwgJ29sZCBcImFtb3VudFwiIGZpZWxkIG11c3Qgbm90IGV4aXN0IG9uIEJhbGFuY2VXaXRoZHJhd2FsJyk7XG4gICAgICBzaG91bGQubm90LmV4aXN0KGJ3LnR5cGVfLCAnb2xkIFwidHlwZV9cIiBmaWVsZCBtdXN0IG5vdCBleGlzdCBvbiBCYWxhbmNlV2l0aGRyYXdhbCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIEJDUyBieXRlcyB0aGF0IGRlY29kZSBiYWNrIHRvIEZ1bmRzV2l0aGRyYXdhbCB3aXRoIGNvcnJlY3QgYW1vdW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHggPSBhd2FpdCBidWlsZFNwb25zb3JlZFR4V2l0aEFkZHJlc3NCYWxhbmNlKCk7XG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IFN1aVRyYW5zYWN0aW9uLmRlc2VyaWFsaXplU3VpVHJhbnNhY3Rpb24ocmF3VHgpO1xuICAgICAgY29uc3QgaW5wdXRzID0gZGVzZXJpYWxpemVkLnR4LmlucHV0cyBhcyBhbnlbXTtcblxuICAgICAgY29uc3QgYndJbnB1dCA9IGlucHV0cy5maW5kKFxuICAgICAgICAoaW5wKSA9PiBpbnA/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWQgfHwgaW5wPy52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICAgIHNob3VsZC5leGlzdChid0lucHV0LCAnQmFsYW5jZVdpdGhkcmF3YWwgbXVzdCBiZSBwcmVzZW50IGluIGRlc2VyaWFsaXplZCBpbnB1dHMnKTtcblxuICAgICAgY29uc3QgYncgPSBid0lucHV0LkJhbGFuY2VXaXRoZHJhd2FsID8/IGJ3SW5wdXQudmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsO1xuXG4gICAgICAvLyBGdW5kc1dpdGhkcmF3YWwgc3RydWN0dXJlIChub3Qgb2xkIHthbW91bnQsIHR5cGVffSlcbiAgICAgIHNob3VsZC5leGlzdChidy5yZXNlcnZhdGlvbiwgJ3Jlc2VydmF0aW9uIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCcpO1xuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnJlc2VydmF0aW9uLk1heEFtb3VudFU2NCwgJ01heEFtb3VudFU2NCBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXAnKTtcbiAgICAgIGJ3LnJlc2VydmF0aW9uLk1heEFtb3VudFU2NC50b1N0cmluZygpLnNob3VsZC5lcXVhbChBTU9VTlQpO1xuXG4gICAgICBzaG91bGQuZXhpc3QoYncudHlwZUFyZywgJ3R5cGVBcmcgbXVzdCBzdXJ2aXZlIEJDUyByb3VuZC10cmlwJyk7XG4gICAgICBzaG91bGQuZXhpc3QoYncudHlwZUFyZy5CYWxhbmNlLCAndHlwZUFyZy5CYWxhbmNlIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCcpO1xuXG4gICAgICBzaG91bGQuZXhpc3QoYncud2l0aGRyYXdGcm9tLCAnd2l0aGRyYXdGcm9tIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzZXJpYWxpemUgdG9Kc29uKCkgd2l0aG91dCBhIEJpZ0ludCByZXBsYWNlciAobm8gVHlwZUVycm9yKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgYnVpbGRTcG9uc29yZWRUeFdpdGhBZGRyZXNzQmFsYW5jZSgpO1xuICAgICAgc2hvdWxkLmRvZXNOb3RUaHJvdyhcbiAgICAgICAgKCkgPT4gSlNPTi5zdHJpbmdpZnkodHgudG9Kc29uKCkpLFxuICAgICAgICAnSlNPTi5zdHJpbmdpZnkodHgudG9Kc29uKCkpIG11c3Qgbm90IHRocm93IOKAlCBCYWxhbmNlV2l0aGRyYXdhbCBhbW91bnQgbXVzdCBub3QgYmUgc3RvcmVkIGFzIEJpZ0ludCdcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHByZXNlcnZlIGZ1bmRzSW5BZGRyZXNzQmFsYW5jZSBhbW91bnQgdGhyb3VnaCBmdWxsIHJvdW5kLXRyaXAnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IGJ1aWxkU3BvbnNvcmVkVHhXaXRoQWRkcmVzc0JhbGFuY2UoKTtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG5cbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gcmVidWlsdFR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgY29uc3QgaW5wdXRzID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHguaW5wdXRzIGFzIGFueVtdO1xuICAgICAgY29uc3QgYndJbnB1dCA9IGlucHV0cy5maW5kKFxuICAgICAgICAoaW5wKSA9PiBpbnA/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWQgfHwgaW5wPy52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICAgIHNob3VsZC5leGlzdChid0lucHV0KTtcbiAgICAgIGNvbnN0IGJ3ID0gYndJbnB1dC5CYWxhbmNlV2l0aGRyYXdhbCA/PyBid0lucHV0LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbDtcbiAgICAgIGJ3LnJlc2VydmF0aW9uLk1heEFtb3VudFU2NC50b1N0cmluZygpLnNob3VsZC5lcXVhbChBTU9VTlQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBQYXRoIDJiOiBzZWxmLXBheSwgZW1wdHkgcGF5bWVudCDigJQgdXNlcyB3aXRoZHJhd2FsK3JlZGVlbV9mdW5kcyBpbnN0ZWFkIG9mIFNwbGl0Q29pbnMoR2FzQ29pbiknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBXaXRoIGdhc0RhdGEucGF5bWVudD1bXSB0aGUgcnVudGltZSBleHBvc2VzIG9ubHkgdGhlIGdhcy1idWRnZXQgYW1vdW50IHZpYSBHYXNDb2luIGZvclxuICAgICAgLy8gUFRCIFNwbGl0Q29pbnMgb3BlcmF0aW9ucy4gU3BsaXRDb2lucyhHYXNDb2luLCBbbGFyZ2VfYW1vdW50XSkgYWx3YXlzIGZhaWxzIHdpdGhcbiAgICAgIC8vIEluc3VmZmljaWVudENvaW5CYWxhbmNlIChjb25maXJtZWQgYnkgcHJvZHVjdGlvbiBmYWlsdXJlcyBKRGJueWJvdGczYXguLi4sIEFUVWJlTFgzLi4uKS5cbiAgICAgIC8vIFBhdGggMmIgZml4ZXMgdGhpcyBieSB3aXRoZHJhd2luZyBmcm9tIHRoZSBhZGRyZXNzIGFjY3VtdWxhdG9yIHZpYSByZWRlZW1fZnVuZHMsXG4gICAgICAvLyBzcGxpdHRpbmcgZnJvbSB0aGF0IGNvaW4gb2JqZWN0LCBhbmQgbWVyZ2luZyB0aGUgMC1iYWxhbmNlIHJlbWFpbmRlciBpbnRvIEdhc0NvaW4uXG4gICAgICBjb25zdCBzZWxmUGF5Tm9QYXltZW50ID0geyAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsIHBheW1lbnQ6IFtdIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiB0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MsIGFtb3VudDogQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNlbGZQYXlOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShBTU9VTlQpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcblxuICAgICAgLy8gR2FzIG93bmVyIG11c3QgZXF1YWwgc2VuZGVyIChzZWxmLXBheSlcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIC8vIFBheW1lbnQgbXVzdCBiZSBlbXB0eSDigJQgZ2FzIGZ1bmRlZCBmcm9tIGFkZHJlc3MgYmFsYW5jZSBieSB0aGUgcnVudGltZVxuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIC8vIFBhdGggMmI6IEJhbGFuY2VXaXRoZHJhd2FsIGlucHV0IE1VU1QgYmUgcHJlc2VudCAod2l0aGRyYXdhbCtyZWRlZW1fZnVuZHMgYXBwcm9hY2gpXG4gICAgICBjb25zdCBpbnB1dHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC5pbnB1dHMgYXMgYW55W107XG4gICAgICBjb25zdCBid0lucHV0ID0gaW5wdXRzLmZpbmQoXG4gICAgICAgIChpbnApID0+IGlucD8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZCB8fCBpbnA/LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkXG4gICAgICApO1xuICAgICAgc2hvdWxkLmV4aXN0KGJ3SW5wdXQsICdQYXRoIDJiOiBCYWxhbmNlV2l0aGRyYXdhbCBpbnB1dCBtdXN0IGJlIHByZXNlbnQnKTtcbiAgICAgIGNvbnN0IGJ3ID0gYndJbnB1dC5CYWxhbmNlV2l0aGRyYXdhbCA/PyBid0lucHV0LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbDtcbiAgICAgIGJ3LnJlc2VydmF0aW9uLk1heEFtb3VudFU2NC50b1N0cmluZygpLnNob3VsZC5lcXVhbChBTU9VTlQpO1xuXG4gICAgICAvLyBGaXJzdCBjb21tYW5kIG11c3QgYmUgTW92ZUNhbGwocmVkZWVtX2Z1bmRzKSwgTk9UIFNwbGl0Q29pbnMoR2FzQ29pbilcbiAgICAgIGNvbnN0IGNvbW1hbmRzID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHgudHJhbnNhY3Rpb25zIGFzIGFueVtdO1xuICAgICAgY29tbWFuZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJyk7XG4gICAgICBjb21tYW5kc1swXS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgLy8gRm9sbG93ZWQgYnk6IFNwbGl0Q29pbnMoYWRkckNvaW4pLCBUcmFuc2Zlck9iamVjdHMsIE1lcmdlQ29pbnMoR2FzQ29pbiwgYWRkckNvaW4pXG4gICAgICBjb21tYW5kc1sxXS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycpO1xuICAgICAgY29tbWFuZHNbMl0ua2luZC5zaG91bGQuZXF1YWwoJ1RyYW5zZmVyT2JqZWN0cycpO1xuICAgICAgY29tbWFuZHNbM10ua2luZC5zaG91bGQuZXF1YWwoJ01lcmdlQ29pbnMnKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSBTdWlUcmFuc2FjdGlvbi5kZXNlcmlhbGl6ZVN1aVRyYW5zYWN0aW9uKHJhd1R4KTtcbiAgICAgIGRlc2VyaWFsaXplZC5zZW5kZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIGRlc2VyaWFsaXplZC5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICBkZXNlcmlhbGl6ZWQuZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIC8vIEJhbGFuY2VXaXRoZHJhd2FsIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcFxuICAgICAgY29uc3QgZGVjb2RlZElucHV0cyA9IGRlc2VyaWFsaXplZC50eC5pbnB1dHMgYXMgYW55W107XG4gICAgICBjb25zdCBkZWNvZGVkQndJbnB1dCA9IGRlY29kZWRJbnB1dHMuZmluZChcbiAgICAgICAgKGlucDogYW55KSA9PiBpbnA/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWQgfHwgaW5wPy52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICAgIHNob3VsZC5leGlzdChkZWNvZGVkQndJbnB1dCwgJ0JhbGFuY2VXaXRoZHJhd2FsIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCBmb3IgUGF0aCAyYicpO1xuXG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIFBhdGggMmIgd2l0aCBWYWxpZER1cmluZyBleHBpcmF0aW9uIChzZWxmLXBheSwgZW1wdHkgcGF5bWVudCknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBQYXRoIDJiIHdpdGggVmFsaWREdXJpbmcgZXhwaXJhdGlvbiDigJQgcmVxdWlyZWQgd2hlbiBnYXNEYXRhLnBheW1lbnQ9W10gdG8gcHJldmVudFxuICAgICAgLy8gcmVwbGF5IGF0dGFja3MuIFVzZXMgd2l0aGRyYXdhbCtyZWRlZW1fZnVuZHMgdG8gbWF0ZXJpYWxpc2UgdHJhbnNmZXIgYW1vdW50IGZyb20gdGhlXG4gICAgICAvLyBhZGRyZXNzIGFjY3VtdWxhdG9yLCBOT1QgU3BsaXRDb2lucyhHYXNDb2luKSB3aGljaCBmYWlscyB3aXRoIEluc3VmZmljaWVudENvaW5CYWxhbmNlLlxuICAgICAgY29uc3QgR0VORVNJU19DSEFJTl9JRCA9ICdHQUZwQ0NjUkN4VGRGZlVFTWJRYmtMQmFaeTJSTmlHQWZ2RkJoTU5wcTJrVCc7XG4gICAgICBjb25zdCBzZWxmUGF5Tm9QYXltZW50ID0geyAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsIHBheW1lbnQ6IFtdIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiB0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MsIGFtb3VudDogQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNlbGZQYXlOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShBTU9VTlQpO1xuICAgICAgdHhCdWlsZGVyLmV4cGlyYXRpb24oe1xuICAgICAgICBWYWxpZER1cmluZzoge1xuICAgICAgICAgIG1pbkVwb2NoOiB7IFNvbWU6IDUwMCB9LFxuICAgICAgICAgIG1heEVwb2NoOiB7IFNvbWU6IDUwMSB9LFxuICAgICAgICAgIG1pblRpbWVzdGFtcDogeyBOb25lOiBudWxsIH0sXG4gICAgICAgICAgbWF4VGltZXN0YW1wOiB7IE5vbmU6IG51bGwgfSxcbiAgICAgICAgICBjaGFpbjogR0VORVNJU19DSEFJTl9JRCxcbiAgICAgICAgICBub25jZTogMHhkZWFkYmVlZixcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcblxuICAgICAgLy8gU2VsZi1wYXk6IG93bmVyID09PSBzZW5kZXIsIHBheW1lbnQgZW1wdHlcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICAvLyBQYXRoIDJiOiBCYWxhbmNlV2l0aGRyYXdhbCBpbnB1dCBNVVNUIGJlIHByZXNlbnRcbiAgICAgIGNvbnN0IGlucHV0cyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LmlucHV0cyBhcyBhbnlbXTtcbiAgICAgIGNvbnN0IGJ3SW5wdXQgPSBpbnB1dHMuZmluZChcbiAgICAgICAgKGlucCkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQuZXhpc3QoYndJbnB1dCwgJ1BhdGggMmI6IEJhbGFuY2VXaXRoZHJhd2FsIGlucHV0IG11c3QgYmUgcHJlc2VudCcpO1xuXG4gICAgICAvLyBGaXJzdCBjb21tYW5kOiBNb3ZlQ2FsbChyZWRlZW1fZnVuZHMpLCBOT1QgU3BsaXRDb2lucyhHYXNDb2luKVxuICAgICAgY29uc3QgY29tbWFuZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG4gICAgICBjb21tYW5kc1swXS5raW5kLnNob3VsZC5lcXVhbCgnTW92ZUNhbGwnKTtcbiAgICAgIGNvbW1hbmRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcblxuICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gU3VpVHJhbnNhY3Rpb24uZGVzZXJpYWxpemVTdWlUcmFuc2FjdGlvbihyYXdUeCk7XG4gICAgICBkZXNlcmlhbGl6ZWQuc2VuZGVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICBkZXNlcmlhbGl6ZWQuZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIGNvbnN0IGV4cGlyYXRpb24gPSAoZGVzZXJpYWxpemVkLmV4cGlyYXRpb24gYXMgYW55KT8uVmFsaWREdXJpbmc7XG4gICAgICBzaG91bGQuZXhpc3QoZXhwaXJhdGlvbiwgJ1ZhbGlkRHVyaW5nIGV4cGlyYXRpb24gbXVzdCBzdXJ2aXZlIEJDUyByb3VuZC10cmlwJyk7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5taW5FcG9jaD8uU29tZSA/PyBleHBpcmF0aW9uLm1pbkVwb2NoKS5zaG91bGQuZXF1YWwoNTAwKTtcbiAgICAgIE51bWJlcihleHBpcmF0aW9uLm1heEVwb2NoPy5Tb21lID8/IGV4cGlyYXRpb24ubWF4RXBvY2gpLnNob3VsZC5lcXVhbCg1MDEpO1xuICAgICAgZXhwaXJhdGlvbi5jaGFpbi5zaG91bGQuZXF1YWwoR0VORVNJU19DSEFJTl9JRCk7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5ub25jZSkuc2hvdWxkLmVxdWFsKDB4ZGVhZGJlZWYpO1xuXG4gICAgICAvLyBCYWxhbmNlV2l0aGRyYXdhbCBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXBcbiAgICAgIGNvbnN0IGRlY29kZWRJbnB1dHMgPSBkZXNlcmlhbGl6ZWQudHguaW5wdXRzIGFzIGFueVtdO1xuICAgICAgY29uc3QgZGVjb2RlZEJ3SW5wdXQgPSBkZWNvZGVkSW5wdXRzLmZpbmQoXG4gICAgICAgIChpbnA6IGFueSkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQuZXhpc3QoZGVjb2RlZEJ3SW5wdXQsICdCYWxhbmNlV2l0aGRyYXdhbCBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXAgZm9yIFBhdGggMmInKTtcblxuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhbmQgY29ycmVjdGx5IGRlY29kZSBhIE1vdmVDYWxsIHRvIDB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzIHdpdGggQmFsYW5jZVdpdGhkcmF3YWwgYXJnJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHggPSBhd2FpdCBidWlsZFNwb25zb3JlZFR4V2l0aEFkZHJlc3NCYWxhbmNlKCk7XG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgY29uc3QgY29tbWFuZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG5cbiAgICAgIGNvbW1hbmRzWzBdLmtpbmQuc2hvdWxkLmVxdWFsKCdNb3ZlQ2FsbCcpO1xuICAgICAgY29tbWFuZHNbMF0udGFyZ2V0LnNob3VsZC5lcXVhbCgnMHgyOjpjb2luOjpyZWRlZW1fZnVuZHMnKTtcbiAgICAgIGNvbW1hbmRzWzBdLnR5cGVBcmd1bWVudHNbMF0uc2hvdWxkLmVxdWFsKCcweDI6OnN1aTo6U1VJJyk7XG5cbiAgICAgIC8vIFRoZSBhcmd1bWVudCB0byByZWRlZW1fZnVuZHMgbXVzdCByZWZlcmVuY2UgdGhlIEJhbGFuY2VXaXRoZHJhd2FsIGlucHV0IChpbmRleCAwKVxuICAgICAgY29uc3QgYXJnID0gY29tbWFuZHNbMF0uYXJndW1lbnRzWzBdO1xuICAgICAgYXJnLmtpbmQuc2hvdWxkLmVxdWFsKCdJbnB1dCcpO1xuICAgICAgYXJnLmluZGV4LnNob3VsZC5lcXVhbCgwKTtcbiAgICAgIGFyZy50eXBlLnNob3VsZC5lcXVhbCgnb2JqZWN0Jyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==
|