@bitgo-beta/sdk-coin-sui 3.0.3-beta.172 → 3.0.3-beta.1721
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 +264 -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 +44 -1
- package/dist/src/lib/transferBuilder.d.ts.map +1 -1
- package/dist/src/lib/transferBuilder.js +208 -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 +125 -10
- 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 +250 -20
- 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 +463 -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 +774 -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 -390
|
@@ -0,0 +1,774 @@
|
|
|
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 a self-pay transfer using only address balance (empty payment)', async function () {
|
|
294
|
+
const gasDataNoPayment = {
|
|
295
|
+
...testData.gasDataWithoutGasPayment,
|
|
296
|
+
payment: [],
|
|
297
|
+
};
|
|
298
|
+
const txBuilder = factory.getTransferBuilder();
|
|
299
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
300
|
+
txBuilder.sender(testData.sender.address);
|
|
301
|
+
txBuilder.send(testData.recipients);
|
|
302
|
+
txBuilder.gasData(gasDataNoPayment);
|
|
303
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
304
|
+
const tx = await txBuilder.build();
|
|
305
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
306
|
+
const suiTx = tx;
|
|
307
|
+
suiTx.suiTransaction.gasData.payment.length.should.equal(0);
|
|
308
|
+
// Self-pay path: SplitCoins(GasCoin, [amount]) — no MoveCall needed
|
|
309
|
+
const programmableTx = suiTx.suiTransaction.tx;
|
|
310
|
+
programmableTx.transactions[0].kind.should.equal('SplitCoins');
|
|
311
|
+
const rawTx = tx.toBroadcastFormat();
|
|
312
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
313
|
+
// Round-trip: rebuild from raw
|
|
314
|
+
const rebuilder = factory.from(rawTx);
|
|
315
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
316
|
+
const rebuiltTx = await rebuilder.build();
|
|
317
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
318
|
+
});
|
|
319
|
+
it('should build a self-pay transfer with coin objects + address balance', async function () {
|
|
320
|
+
const txBuilder = factory.getTransferBuilder();
|
|
321
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
322
|
+
txBuilder.sender(testData.sender.address);
|
|
323
|
+
txBuilder.send(testData.recipients);
|
|
324
|
+
txBuilder.gasData(testData.gasData);
|
|
325
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
326
|
+
const tx = await txBuilder.build();
|
|
327
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
328
|
+
const suiTx = tx;
|
|
329
|
+
// Self-pay path: SplitCoins(GasCoin) — protocol merges coin objects + address balance automatically
|
|
330
|
+
const programmableTx = suiTx.suiTransaction.tx;
|
|
331
|
+
programmableTx.transactions[0].kind.should.equal('SplitCoins');
|
|
332
|
+
const rawTx = tx.toBroadcastFormat();
|
|
333
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
334
|
+
});
|
|
335
|
+
it('should build a sponsored transfer with coin objects + address balance', async function () {
|
|
336
|
+
const inputObjects = testData.generateObjects(2);
|
|
337
|
+
const sponsoredGasData = {
|
|
338
|
+
...testData.gasData,
|
|
339
|
+
owner: testData.feePayer.address,
|
|
340
|
+
};
|
|
341
|
+
const txBuilder = factory.getTransferBuilder();
|
|
342
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
343
|
+
txBuilder.sender(testData.sender.address);
|
|
344
|
+
txBuilder.send(testData.recipients);
|
|
345
|
+
txBuilder.gasData(sponsoredGasData);
|
|
346
|
+
txBuilder.inputObjects(inputObjects);
|
|
347
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
348
|
+
const tx = await txBuilder.build();
|
|
349
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
350
|
+
const suiTx = tx;
|
|
351
|
+
suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
|
|
352
|
+
// Sponsored path: MoveCall(redeem_funds) + MergeCoins + SplitCoins
|
|
353
|
+
const programmableTx = suiTx.suiTransaction.tx;
|
|
354
|
+
programmableTx.transactions[0].kind.should.equal('MoveCall');
|
|
355
|
+
programmableTx.transactions[0].target.should.equal('0x2::coin::redeem_funds');
|
|
356
|
+
programmableTx.transactions[1].kind.should.equal('MergeCoins');
|
|
357
|
+
programmableTx.transactions[2].kind.should.equal('SplitCoins');
|
|
358
|
+
const rawTx = tx.toBroadcastFormat();
|
|
359
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
360
|
+
// Round-trip
|
|
361
|
+
const rebuilder = factory.from(rawTx);
|
|
362
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
363
|
+
const rebuiltTx = await rebuilder.build();
|
|
364
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
365
|
+
});
|
|
366
|
+
it('should build a sponsored transfer with address balance only (no coin inputObjects)', async function () {
|
|
367
|
+
const sponsoredGasData = {
|
|
368
|
+
...testData.gasData,
|
|
369
|
+
owner: testData.feePayer.address,
|
|
370
|
+
};
|
|
371
|
+
const txBuilder = factory.getTransferBuilder();
|
|
372
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
373
|
+
txBuilder.sender(testData.sender.address);
|
|
374
|
+
txBuilder.send(testData.recipients);
|
|
375
|
+
txBuilder.gasData(sponsoredGasData);
|
|
376
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
377
|
+
const tx = await txBuilder.build();
|
|
378
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
379
|
+
// Path 1b: withdrawal → redeem_funds → SplitCoins(addrCoin) → TransferObjects
|
|
380
|
+
// Sponsor's gas coins remain in gasData.payment; tx.gas is NOT used for the transfer amount.
|
|
381
|
+
const suiTx = tx;
|
|
382
|
+
suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
|
|
383
|
+
const programmableTx = suiTx.suiTransaction.tx;
|
|
384
|
+
programmableTx.transactions[0].kind.should.equal('MoveCall');
|
|
385
|
+
programmableTx.transactions[0].target.should.equal('0x2::coin::redeem_funds');
|
|
386
|
+
programmableTx.transactions[1].kind.should.equal('SplitCoins');
|
|
387
|
+
const rawTx = tx.toBroadcastFormat();
|
|
388
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
389
|
+
// Round-trip: rebuild from raw
|
|
390
|
+
const rebuilder = factory.from(rawTx);
|
|
391
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
392
|
+
const rebuiltTx = await rebuilder.build();
|
|
393
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
394
|
+
});
|
|
395
|
+
it('should build Path 1b send-all: sponsored addr-balance-only, no change (MergeCoins consumes addrCoin)', async function () {
|
|
396
|
+
// Reproduces the real on-chain failure: UnusedValueWithoutDrop { result_idx: 0 }
|
|
397
|
+
// Occurs when redeem_funds returns addrCoin, SplitCoins drains it completely, and the
|
|
398
|
+
// 0-balance source coin is never consumed. Fix: MergeCoins(gas, [addrCoin]) at the end.
|
|
399
|
+
const SEND_AMOUNT = '1000000'; // 0.001 SUI — same as the failing tx
|
|
400
|
+
const sponsoredGasData = {
|
|
401
|
+
...testData.gasData,
|
|
402
|
+
owner: testData.feePayer.address,
|
|
403
|
+
};
|
|
404
|
+
const txBuilder = factory.getTransferBuilder();
|
|
405
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
406
|
+
txBuilder.sender(testData.sender.address);
|
|
407
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: SEND_AMOUNT }]);
|
|
408
|
+
txBuilder.gasData(sponsoredGasData);
|
|
409
|
+
txBuilder.fundsInAddressBalance(SEND_AMOUNT); // send-all: balance == recipient amount
|
|
410
|
+
const tx = await txBuilder.build();
|
|
411
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
412
|
+
const suiTx = tx;
|
|
413
|
+
const cmds = suiTx.suiTransaction.tx.transactions;
|
|
414
|
+
// Expected command sequence for Path 1b send-all:
|
|
415
|
+
// 0: MoveCall (redeem_funds) — withdraw addrCoin
|
|
416
|
+
// 1: SplitCoins(addrCoin) — split recipient amount off addrCoin
|
|
417
|
+
// 2: TransferObjects([split]) — send to recipient
|
|
418
|
+
// 3: MergeCoins(gas, [addrCoin]) — consume the now-zero-balance addrCoin
|
|
419
|
+
cmds[0].kind.should.equal('MoveCall');
|
|
420
|
+
cmds[0].target.should.equal('0x2::coin::redeem_funds');
|
|
421
|
+
cmds[1].kind.should.equal('SplitCoins');
|
|
422
|
+
cmds[2].kind.should.equal('TransferObjects');
|
|
423
|
+
cmds[3].kind.should.equal('MergeCoins', 'expected MergeCoins to consume 0-balance addrCoin after send-all');
|
|
424
|
+
// Recipient parsing must not be affected by the trailing MergeCoins
|
|
425
|
+
const recipients = utils_1.default.getRecipients(suiTx.suiTransaction);
|
|
426
|
+
recipients.length.should.equal(1);
|
|
427
|
+
recipients[0].address.should.equal(testData.recipients[0].address);
|
|
428
|
+
recipients[0].amount.should.equal(SEND_AMOUNT);
|
|
429
|
+
// Round-trip
|
|
430
|
+
const rawTx = tx.toBroadcastFormat();
|
|
431
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
432
|
+
const rebuilder = factory.from(rawTx);
|
|
433
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
434
|
+
const rebuiltTx = await rebuilder.build();
|
|
435
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
436
|
+
});
|
|
437
|
+
it('should build Path 1b with change: sponsored addr-balance-only, excess returned to sender', async function () {
|
|
438
|
+
// fundsInAddressBalance exceeds the total recipient amount → change must be returned to
|
|
439
|
+
// the sender as an extra TransferObjects([addrCoin], sender). The transaction parser must
|
|
440
|
+
// skip this change transfer and only report actual recipients.
|
|
441
|
+
const SEND_AMOUNT = '100'; // each of the two testData.recipients gets 100
|
|
442
|
+
const EXCESS = '9999900'; // fundsInAddressBalance = 10_000_000, total send = 200
|
|
443
|
+
const FUNDS_BALANCE = (Number(SEND_AMOUNT) * testData.recipients.length + Number(EXCESS)).toString();
|
|
444
|
+
const sponsoredGasData = {
|
|
445
|
+
...testData.gasData,
|
|
446
|
+
owner: testData.feePayer.address,
|
|
447
|
+
};
|
|
448
|
+
const txBuilder = factory.getTransferBuilder();
|
|
449
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
450
|
+
txBuilder.sender(testData.sender.address);
|
|
451
|
+
txBuilder.send(testData.recipients); // 2 recipients × 100 MIST = 200 MIST total
|
|
452
|
+
txBuilder.gasData(sponsoredGasData);
|
|
453
|
+
txBuilder.fundsInAddressBalance(FUNDS_BALANCE); // 10_000_000 > 200 → has change
|
|
454
|
+
const tx = await txBuilder.build();
|
|
455
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
456
|
+
const suiTx = tx;
|
|
457
|
+
const cmds = suiTx.suiTransaction.tx.transactions;
|
|
458
|
+
// Expected sequence for Path 1b with change (2 recipients):
|
|
459
|
+
// 0: MoveCall (redeem_funds)
|
|
460
|
+
// 1: SplitCoins — recipient 0
|
|
461
|
+
// 2: TransferObjects — recipient 0
|
|
462
|
+
// 3: SplitCoins — recipient 1
|
|
463
|
+
// 4: TransferObjects — recipient 1
|
|
464
|
+
// 5: TransferObjects([addrCoin], sender) — change back to sender
|
|
465
|
+
cmds[0].kind.should.equal('MoveCall');
|
|
466
|
+
cmds[0].target.should.equal('0x2::coin::redeem_funds');
|
|
467
|
+
const lastCmd = cmds[cmds.length - 1];
|
|
468
|
+
lastCmd.kind.should.equal('TransferObjects', 'last command must be the change transfer');
|
|
469
|
+
// The last TransferObjects returns change to the *sender*, not a recipient
|
|
470
|
+
const changeAddrInput = suiTx.suiTransaction.tx.inputs[lastCmd.address.index];
|
|
471
|
+
const changeAddr = utils_1.default.getAddress(changeAddrInput);
|
|
472
|
+
changeAddr.should.equal(testData.sender.address, 'change must go back to sender');
|
|
473
|
+
// Parser must return only the actual recipients, not the change transfer
|
|
474
|
+
const recipients = utils_1.default.getRecipients(suiTx.suiTransaction);
|
|
475
|
+
recipients.length.should.equal(testData.recipients.length);
|
|
476
|
+
recipients[0].address.should.equal(testData.recipients[0].address);
|
|
477
|
+
recipients[0].amount.should.equal(SEND_AMOUNT);
|
|
478
|
+
recipients[1].address.should.equal(testData.recipients[1].address);
|
|
479
|
+
recipients[1].amount.should.equal(SEND_AMOUNT);
|
|
480
|
+
// Round-trip
|
|
481
|
+
const rawTx = tx.toBroadcastFormat();
|
|
482
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
483
|
+
const rebuilder = factory.from(rawTx);
|
|
484
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
485
|
+
const rebuiltTx = await rebuilder.build();
|
|
486
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
487
|
+
});
|
|
488
|
+
it('should build a sponsored tx gas paid from sponsor address balance (empty payment)', async function () {
|
|
489
|
+
const inputObjects = testData.generateObjects(1);
|
|
490
|
+
const sponsoredGasDataNoPayment = {
|
|
491
|
+
payment: [],
|
|
492
|
+
owner: testData.feePayer.address,
|
|
493
|
+
price: testData.gasData.price,
|
|
494
|
+
budget: testData.gasData.budget,
|
|
495
|
+
};
|
|
496
|
+
const txBuilder = factory.getTransferBuilder();
|
|
497
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
498
|
+
txBuilder.sender(testData.sender.address);
|
|
499
|
+
txBuilder.send(testData.recipients);
|
|
500
|
+
txBuilder.gasData(sponsoredGasDataNoPayment);
|
|
501
|
+
txBuilder.inputObjects(inputObjects);
|
|
502
|
+
const tx = await txBuilder.build();
|
|
503
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
504
|
+
const suiTx = tx;
|
|
505
|
+
suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
|
|
506
|
+
suiTx.suiTransaction.gasData.payment.length.should.equal(0);
|
|
507
|
+
// Sponsored path with coin objects, no address balance withdrawal
|
|
508
|
+
const programmableTx = suiTx.suiTransaction.tx;
|
|
509
|
+
programmableTx.transactions[0].kind.should.equal('SplitCoins');
|
|
510
|
+
const rawTx = tx.toBroadcastFormat();
|
|
511
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
512
|
+
});
|
|
513
|
+
it('should round-trip a self-pay transfer with Epoch expiration via fromBytes', async function () {
|
|
514
|
+
// Regression test for the BigInt round-trip bug:
|
|
515
|
+
// BCS.U64 deserializes u64 as BigInt, but the previous superstruct schema used integer()
|
|
516
|
+
// which rejected BigInt, causing fromBytes() to throw a StructError at "expiration".
|
|
517
|
+
// StringEncodedBigint now accepts string | number | bigint, fixing the round-trip.
|
|
518
|
+
const gasDataNoPayment = {
|
|
519
|
+
...testData.gasDataWithoutGasPayment,
|
|
520
|
+
payment: [],
|
|
521
|
+
};
|
|
522
|
+
const txBuilder = factory.getTransferBuilder();
|
|
523
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
524
|
+
txBuilder.sender(testData.sender.address);
|
|
525
|
+
txBuilder.send(testData.recipients);
|
|
526
|
+
txBuilder.gasData(gasDataNoPayment);
|
|
527
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
528
|
+
txBuilder.expiration({ Epoch: 324 }); // number input
|
|
529
|
+
const tx = await txBuilder.build();
|
|
530
|
+
const rawTx = tx.toBroadcastFormat();
|
|
531
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
532
|
+
// fromBytes must not throw StructError — this was the failing case before the fix
|
|
533
|
+
should_1.default.doesNotThrow(() => {
|
|
534
|
+
const rebuilder = factory.from(rawTx);
|
|
535
|
+
should_1.default.exist(rebuilder);
|
|
536
|
+
});
|
|
537
|
+
// Full round-trip: rebuilt tx must serialize identically
|
|
538
|
+
const rebuilder = factory.from(rawTx);
|
|
539
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
540
|
+
const rebuiltTx = await rebuilder.build();
|
|
541
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
542
|
+
// Epoch value must survive the round-trip regardless of BigInt/number representation
|
|
543
|
+
const rebuiltJson = rebuiltTx.toJson();
|
|
544
|
+
const epochVal = rebuiltJson.expiration?.Epoch;
|
|
545
|
+
should_1.default.exist(epochVal);
|
|
546
|
+
Number(epochVal).should.equal(324);
|
|
547
|
+
});
|
|
548
|
+
it('should round-trip a self-pay transfer with ValidDuring expiration via fromBytes', async function () {
|
|
549
|
+
// Verifies the full 6-field ValidDuringExpiration BCS schema:
|
|
550
|
+
// minEpoch/maxEpoch as Option<u64>, minTimestamp/maxTimestamp as Option<u64> (None),
|
|
551
|
+
// chain as 32-byte Base58 ObjectDigest, nonce as u32.
|
|
552
|
+
// Uses a real mainnet genesis checkpoint digest (32 bytes, Base58).
|
|
553
|
+
const GENESIS_CHAIN_ID = 'GAFpCCcRCxTdFfUEMbQbkLBaZy2RNiGAfvFBhMNpq2kT';
|
|
554
|
+
const FUNDS_IN_ADDRESS_BALANCE = '5000000000';
|
|
555
|
+
const gasDataNoPayment = {
|
|
556
|
+
...testData.gasDataWithoutGasPayment,
|
|
557
|
+
payment: [],
|
|
558
|
+
};
|
|
559
|
+
const txBuilder = factory.getTransferBuilder();
|
|
560
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
561
|
+
txBuilder.sender(testData.sender.address);
|
|
562
|
+
txBuilder.send(testData.recipients);
|
|
563
|
+
txBuilder.gasData(gasDataNoPayment);
|
|
564
|
+
txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
|
|
565
|
+
txBuilder.expiration({
|
|
566
|
+
ValidDuring: {
|
|
567
|
+
minEpoch: { Some: 500 },
|
|
568
|
+
maxEpoch: { Some: 501 },
|
|
569
|
+
minTimestamp: { None: null },
|
|
570
|
+
maxTimestamp: { None: null },
|
|
571
|
+
chain: GENESIS_CHAIN_ID,
|
|
572
|
+
nonce: 0xdeadbeef,
|
|
573
|
+
},
|
|
574
|
+
});
|
|
575
|
+
const tx = await txBuilder.build();
|
|
576
|
+
const rawTx = tx.toBroadcastFormat();
|
|
577
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
578
|
+
// fromBytes must not throw — ValidDuring fields must survive deserialization
|
|
579
|
+
const rebuilder = factory.from(rawTx);
|
|
580
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
581
|
+
const rebuiltTx = await rebuilder.build();
|
|
582
|
+
// BCS round-trip: serialized bytes must be identical
|
|
583
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
584
|
+
// All ValidDuring fields must survive the round-trip
|
|
585
|
+
const expiration = rebuiltTx.toJson().expiration?.ValidDuring;
|
|
586
|
+
should_1.default.exist(expiration);
|
|
587
|
+
Number(expiration.minEpoch?.Some ?? expiration.minEpoch).should.equal(500);
|
|
588
|
+
Number(expiration.maxEpoch?.Some ?? expiration.maxEpoch).should.equal(501);
|
|
589
|
+
expiration.chain.should.equal(GENESIS_CHAIN_ID);
|
|
590
|
+
Number(expiration.nonce).should.equal(0xdeadbeef);
|
|
591
|
+
});
|
|
592
|
+
});
|
|
593
|
+
describe('BalanceWithdrawal BCS encoding (FundsWithdrawal format)', () => {
|
|
594
|
+
const AMOUNT = '100000000'; // 0.1 SUI in MIST
|
|
595
|
+
const sponsoredGasData = {
|
|
596
|
+
...testData.gasData,
|
|
597
|
+
owner: testData.feePayer.address,
|
|
598
|
+
};
|
|
599
|
+
async function buildSponsoredTxWithAddressBalance() {
|
|
600
|
+
const txBuilder = factory.getTransferBuilder();
|
|
601
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
602
|
+
txBuilder.sender(testData.sender.address);
|
|
603
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
|
|
604
|
+
txBuilder.gasData(sponsoredGasData);
|
|
605
|
+
txBuilder.fundsInAddressBalance(AMOUNT);
|
|
606
|
+
return txBuilder.build();
|
|
607
|
+
}
|
|
608
|
+
it('should encode BalanceWithdrawal input with FundsWithdrawal structure (reservation/typeArg/withdrawFrom)', async function () {
|
|
609
|
+
const tx = await buildSponsoredTxWithAddressBalance();
|
|
610
|
+
const suiTx = tx;
|
|
611
|
+
const inputs = suiTx.suiTransaction.tx.inputs;
|
|
612
|
+
const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
613
|
+
should_1.default.exist(bwInput, 'BalanceWithdrawal input must be present');
|
|
614
|
+
const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
|
|
615
|
+
should_1.default.exist(bw.reservation, 'reservation field must exist');
|
|
616
|
+
should_1.default.exist(bw.reservation.MaxAmountU64, 'reservation.MaxAmountU64 must exist');
|
|
617
|
+
bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
|
|
618
|
+
should_1.default.exist(bw.typeArg, 'typeArg field must exist');
|
|
619
|
+
should_1.default.exist(bw.typeArg.Balance, 'typeArg.Balance must exist');
|
|
620
|
+
should_1.default.exist(bw.withdrawFrom, 'withdrawFrom field must exist');
|
|
621
|
+
should_1.default.exist(bw.withdrawFrom.Sender !== undefined || bw.withdrawFrom.Sponsor !== undefined, 'withdrawFrom must be Sender or Sponsor');
|
|
622
|
+
// Old format fields must NOT exist directly on bw
|
|
623
|
+
should_1.default.not.exist(bw.amount, 'old "amount" field must not exist on BalanceWithdrawal');
|
|
624
|
+
should_1.default.not.exist(bw.type_, 'old "type_" field must not exist on BalanceWithdrawal');
|
|
625
|
+
});
|
|
626
|
+
it('should produce BCS bytes that decode back to FundsWithdrawal with correct amount', async function () {
|
|
627
|
+
const tx = await buildSponsoredTxWithAddressBalance();
|
|
628
|
+
const rawTx = tx.toBroadcastFormat();
|
|
629
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
630
|
+
const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
|
|
631
|
+
const inputs = deserialized.tx.inputs;
|
|
632
|
+
const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
633
|
+
should_1.default.exist(bwInput, 'BalanceWithdrawal must be present in deserialized inputs');
|
|
634
|
+
const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
|
|
635
|
+
// FundsWithdrawal structure (not old {amount, type_})
|
|
636
|
+
should_1.default.exist(bw.reservation, 'reservation must survive BCS round-trip');
|
|
637
|
+
should_1.default.exist(bw.reservation.MaxAmountU64, 'MaxAmountU64 must survive BCS round-trip');
|
|
638
|
+
bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
|
|
639
|
+
should_1.default.exist(bw.typeArg, 'typeArg must survive BCS round-trip');
|
|
640
|
+
should_1.default.exist(bw.typeArg.Balance, 'typeArg.Balance must survive BCS round-trip');
|
|
641
|
+
should_1.default.exist(bw.withdrawFrom, 'withdrawFrom must survive BCS round-trip');
|
|
642
|
+
});
|
|
643
|
+
it('should serialize toJson() without a BigInt replacer (no TypeError)', async function () {
|
|
644
|
+
const tx = await buildSponsoredTxWithAddressBalance();
|
|
645
|
+
should_1.default.doesNotThrow(() => JSON.stringify(tx.toJson()), 'JSON.stringify(tx.toJson()) must not throw — BalanceWithdrawal amount must not be stored as BigInt');
|
|
646
|
+
});
|
|
647
|
+
it('should preserve fundsInAddressBalance amount through full round-trip', async function () {
|
|
648
|
+
const tx = await buildSponsoredTxWithAddressBalance();
|
|
649
|
+
const rawTx = tx.toBroadcastFormat();
|
|
650
|
+
const rebuilder = factory.from(rawTx);
|
|
651
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
652
|
+
const rebuiltTx = await rebuilder.build();
|
|
653
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
654
|
+
const suiTx = rebuiltTx;
|
|
655
|
+
const inputs = suiTx.suiTransaction.tx.inputs;
|
|
656
|
+
const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
657
|
+
should_1.default.exist(bwInput);
|
|
658
|
+
const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
|
|
659
|
+
bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
|
|
660
|
+
});
|
|
661
|
+
it('should encode gas-from-address-balance (self-pay, empty payment) with no FundsWithdrawal input', async function () {
|
|
662
|
+
// When gasData.payment=[] and sender===gasData.owner, the Sui runtime automatically
|
|
663
|
+
// uses address balance to fund both gas and the transfer via GasCoin.
|
|
664
|
+
// No BalanceWithdrawal CallArg is needed — the runtime handles it implicitly.
|
|
665
|
+
const selfPayNoPayment = { ...testData.gasDataWithoutGasPayment, payment: [] };
|
|
666
|
+
const txBuilder = factory.getTransferBuilder();
|
|
667
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
668
|
+
txBuilder.sender(testData.sender.address);
|
|
669
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
|
|
670
|
+
txBuilder.gasData(selfPayNoPayment);
|
|
671
|
+
txBuilder.fundsInAddressBalance(AMOUNT);
|
|
672
|
+
const tx = await txBuilder.build();
|
|
673
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
674
|
+
const suiTx = tx;
|
|
675
|
+
// Gas owner must equal sender (self-pay)
|
|
676
|
+
suiTx.suiTransaction.gasData.owner.should.equal(testData.sender.address);
|
|
677
|
+
// Payment must be empty — gas funded from address balance by the runtime
|
|
678
|
+
suiTx.suiTransaction.gasData.payment.length.should.equal(0);
|
|
679
|
+
// No BalanceWithdrawal input — runtime handles address balance automatically
|
|
680
|
+
const inputs = suiTx.suiTransaction.tx.inputs;
|
|
681
|
+
const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
682
|
+
should_1.default.not.exist(bwInput, 'self-pay must NOT have a BalanceWithdrawal input — runtime handles it');
|
|
683
|
+
// First command must be SplitCoins(GasCoin) — no redeem_funds needed
|
|
684
|
+
const commands = suiTx.suiTransaction.tx.transactions;
|
|
685
|
+
commands[0].kind.should.equal('SplitCoins');
|
|
686
|
+
const rawTx = tx.toBroadcastFormat();
|
|
687
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
688
|
+
const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
|
|
689
|
+
deserialized.sender.should.equal(testData.sender.address);
|
|
690
|
+
deserialized.gasData.owner.should.equal(testData.sender.address);
|
|
691
|
+
deserialized.gasData.payment.length.should.equal(0);
|
|
692
|
+
// No FundsWithdrawal in decoded inputs — only Pure args
|
|
693
|
+
const decodedInputs = deserialized.tx.inputs;
|
|
694
|
+
decodedInputs
|
|
695
|
+
.every((inp) => inp?.BalanceWithdrawal === undefined && inp?.value?.BalanceWithdrawal === undefined)
|
|
696
|
+
.should.be.true('decoded inputs must contain no FundsWithdrawal for self-pay path');
|
|
697
|
+
const rebuilder = factory.from(rawTx);
|
|
698
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
699
|
+
const rebuiltTx = await rebuilder.build();
|
|
700
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
701
|
+
});
|
|
702
|
+
it('should encode gas-from-address-balance with ValidDuring expiration (self-pay, empty payment)', async function () {
|
|
703
|
+
// When gasData.payment=[] the Sui node requires a ValidDuring expiration to prevent
|
|
704
|
+
// replay attacks. Gas and transfer are both funded from address balance via GasCoin.
|
|
705
|
+
const GENESIS_CHAIN_ID = 'GAFpCCcRCxTdFfUEMbQbkLBaZy2RNiGAfvFBhMNpq2kT';
|
|
706
|
+
const selfPayNoPayment = { ...testData.gasDataWithoutGasPayment, payment: [] };
|
|
707
|
+
const txBuilder = factory.getTransferBuilder();
|
|
708
|
+
txBuilder.type(iface_1.SuiTransactionType.Transfer);
|
|
709
|
+
txBuilder.sender(testData.sender.address);
|
|
710
|
+
txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
|
|
711
|
+
txBuilder.gasData(selfPayNoPayment);
|
|
712
|
+
txBuilder.fundsInAddressBalance(AMOUNT);
|
|
713
|
+
txBuilder.expiration({
|
|
714
|
+
ValidDuring: {
|
|
715
|
+
minEpoch: { Some: 500 },
|
|
716
|
+
maxEpoch: { Some: 501 },
|
|
717
|
+
minTimestamp: { None: null },
|
|
718
|
+
maxTimestamp: { None: null },
|
|
719
|
+
chain: GENESIS_CHAIN_ID,
|
|
720
|
+
nonce: 0xdeadbeef,
|
|
721
|
+
},
|
|
722
|
+
});
|
|
723
|
+
const tx = await txBuilder.build();
|
|
724
|
+
should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
|
|
725
|
+
const suiTx = tx;
|
|
726
|
+
// Self-pay: owner === sender, payment empty
|
|
727
|
+
suiTx.suiTransaction.gasData.owner.should.equal(testData.sender.address);
|
|
728
|
+
suiTx.suiTransaction.gasData.payment.length.should.equal(0);
|
|
729
|
+
// No BalanceWithdrawal input — runtime handles GasCoin from address balance
|
|
730
|
+
const inputs = suiTx.suiTransaction.tx.inputs;
|
|
731
|
+
const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
|
|
732
|
+
should_1.default.not.exist(bwInput, 'self-pay must NOT have a BalanceWithdrawal input');
|
|
733
|
+
// First command: SplitCoins(GasCoin) — no redeem_funds for self-pay
|
|
734
|
+
const commands = suiTx.suiTransaction.tx.transactions;
|
|
735
|
+
commands[0].kind.should.equal('SplitCoins');
|
|
736
|
+
const rawTx = tx.toBroadcastFormat();
|
|
737
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
738
|
+
const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
|
|
739
|
+
deserialized.sender.should.equal(testData.sender.address);
|
|
740
|
+
deserialized.gasData.payment.length.should.equal(0);
|
|
741
|
+
const expiration = deserialized.expiration?.ValidDuring;
|
|
742
|
+
should_1.default.exist(expiration, 'ValidDuring expiration must survive BCS round-trip');
|
|
743
|
+
Number(expiration.minEpoch?.Some ?? expiration.minEpoch).should.equal(500);
|
|
744
|
+
Number(expiration.maxEpoch?.Some ?? expiration.maxEpoch).should.equal(501);
|
|
745
|
+
expiration.chain.should.equal(GENESIS_CHAIN_ID);
|
|
746
|
+
Number(expiration.nonce).should.equal(0xdeadbeef);
|
|
747
|
+
// Inputs must contain no FundsWithdrawal — only Pure args
|
|
748
|
+
const decodedInputs = deserialized.tx.inputs;
|
|
749
|
+
decodedInputs
|
|
750
|
+
.every((inp) => inp?.BalanceWithdrawal === undefined && inp?.value?.BalanceWithdrawal === undefined)
|
|
751
|
+
.should.be.true('decoded inputs must contain no FundsWithdrawal for self-pay path');
|
|
752
|
+
const rebuilder = factory.from(rawTx);
|
|
753
|
+
rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
|
|
754
|
+
const rebuiltTx = await rebuilder.build();
|
|
755
|
+
rebuiltTx.toBroadcastFormat().should.equal(rawTx);
|
|
756
|
+
});
|
|
757
|
+
it('should build and correctly decode a MoveCall to 0x2::coin::redeem_funds with BalanceWithdrawal arg', async function () {
|
|
758
|
+
const tx = await buildSponsoredTxWithAddressBalance();
|
|
759
|
+
const suiTx = tx;
|
|
760
|
+
const commands = suiTx.suiTransaction.tx.transactions;
|
|
761
|
+
commands[0].kind.should.equal('MoveCall');
|
|
762
|
+
commands[0].target.should.equal('0x2::coin::redeem_funds');
|
|
763
|
+
commands[0].typeArguments[0].should.equal('0x2::sui::SUI');
|
|
764
|
+
// The argument to redeem_funds must reference the BalanceWithdrawal input (index 0)
|
|
765
|
+
const arg = commands[0].arguments[0];
|
|
766
|
+
arg.kind.should.equal('Input');
|
|
767
|
+
arg.index.should.equal(0);
|
|
768
|
+
arg.type.should.equal('object');
|
|
769
|
+
const rawTx = tx.toBroadcastFormat();
|
|
770
|
+
should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
|
|
771
|
+
});
|
|
772
|
+
});
|
|
773
|
+
});
|
|
774
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmZXJCdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC91bml0L3RyYW5zYWN0aW9uQnVpbGRlci90cmFuc2ZlckJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsNERBQXlEO0FBQ3pELDhEQUFnRDtBQUNoRCxvREFBNEI7QUFDNUIsbURBQXVEO0FBQ3ZELG1FQUEyQztBQUMzQyw4REFBNkU7QUFDN0Usa0RBQTZGO0FBQzdGLDBEQUErRTtBQUUvRSxRQUFRLENBQUMsc0JBQXNCLEVBQUUsR0FBRyxFQUFFO0lBQ3BDLE1BQU0sT0FBTyxHQUFHLElBQUEscUNBQWlCLEVBQUMsTUFBTSxDQUFDLENBQUM7SUFFMUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUU7UUFDdkIsRUFBRSxDQUFDLDRCQUE0QixFQUFFLEtBQUs7WUFDcEMsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDL0MsU0FBUyxDQUFDLElBQUksQ0FBQywwQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM1QyxTQUFTLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDMUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDcEMsTUFBTSxFQUFFLEdBQUcsTUFBTSxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbkMsZ0JBQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSwwQkFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNDLEVBQXNELENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxPQUFRLENB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cG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7IGdldEJ1aWxkZXJGYWN0b3J5IH0gZnJvbSAnLi4vZ2V0QnVpbGRlckZhY3RvcnknO1xuaW1wb3J0ICogYXMgdGVzdERhdGEgZnJvbSAnLi4vLi4vcmVzb3VyY2VzL3N1aSc7XG5pbXBvcnQgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvblR5cGUgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgdXRpbHMgZnJvbSAnLi4vLi4vLi4vc3JjL2xpYi91dGlscyc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvbiBhcyBTdWlUcmFuc2FjdGlvbiB9IGZyb20gJy4uLy4uLy4uL3NyYy9saWIvdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgU3VpVHJhbnNhY3Rpb25UeXBlLCBUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uIH0gZnJvbSAnLi4vLi4vLi4vc3JjL2xpYi9pZmFjZSc7XG5pbXBvcnQgeyBNQVhfQ09NTUFORF9BUkdTLCBNQVhfR0FTX09CSkVDVFMgfSBmcm9tICcuLi8uLi8uLi9zcmMvbGliL2NvbnN0YW50cyc7XG5cbmRlc2NyaWJlKCdTdWkgVHJhbnNmZXIgQnVpbGRlcicsICgpID0+IHtcbiAgY29uc3QgZmFjdG9yeSA9IGdldEJ1aWxkZXJGYWN0b3J5KCd0c3VpJyk7XG5cbiAgZGVzY3JpYmUoJ1N1Y2NlZWQnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHRyYW5zZmVyIHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEodGVzdERhdGEuZ2FzRGF0YSk7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICAgICh0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPikuc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50IS5zaG91bGQuZGVlcEVxdWFsKFxuICAgICAgICB0ZXN0RGF0YS5jb2luc0dhc1BheW1lbnRcbiAgICAgICk7XG5cbiAgICAgIHR4LmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHguaW5wdXRzWzBdLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBhZGRyZXNzOiB0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyxcbiAgICAgICAgdmFsdWU6ICh0ZXN0RGF0YS5BTU9VTlQgKiAyKS50b1N0cmluZygpLFxuICAgICAgICBjb2luOiAndHN1aScsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICAgIHR4Lm91dHB1dHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcyxcbiAgICAgICAgdmFsdWU6IHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYW1vdW50LFxuICAgICAgICBjb2luOiAndHN1aScsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHB1dHNbMV0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnJlY2lwaWVudHNbMV0uYWRkcmVzcyxcbiAgICAgICAgdmFsdWU6IHRlc3REYXRhLnJlY2lwaWVudHNbMV0uYW1vdW50LFxuICAgICAgICBjb2luOiAndHN1aScsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICAgIHNob3VsZC5lcXVhbChyYXdUeCwgdGVzdERhdGEuVFJBTlNGRVIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHNwb25zb3JlZCB0cmFuc2ZlciB0eCB3aXRoIGlucHV0T2JqZWN0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGlucHV0T2JqZWN0cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIG9iamVjdElkOiAnMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3OCcsXG4gICAgICAgICAgdmVyc2lvbjogMTAwLFxuICAgICAgICAgIGRpZ2VzdDogJzJCOFhLUUo3bWZ4UVBVV3FKSkFHanpCQXppdmtXS3EyY0VhM1c4TEx6MXlCJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG9iamVjdElkOiAnMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMicsXG4gICAgICAgICAgdmVyc2lvbjogMjAwLFxuICAgICAgICAgIGRpZ2VzdDogJ0RvSndYdXo5b1U1WTV2NXZCUmlUZ2lzVlRRdVpRTG1IWldlcUp6ekQ1UVVFJyxcbiAgICAgICAgfSxcbiAgICAgIF07XG5cbiAgICAgIC8vIENyZWF0ZSBnYXMgZGF0YSB3aXRoIGRpZmZlcmVudCBvd25lciAoc3BvbnNvcilcbiAgICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLCAvLyBEaWZmZXJlbnQgZnJvbSBzZW5kZXJcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7IC8vIFNlbmRlclxuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTsgLy8gR2FzIHBhaWQgYnkgc3BvbnNvclxuICAgICAgdHhCdWlsZGVyLmlucHV0T2JqZWN0cyhpbnB1dE9iamVjdHMpOyAvLyBSZXF1aXJlZCBmb3Igc3BvbnNvcmVkIHR4XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuXG4gICAgICAvLyBWZXJpZnkgdHJhbnNhY3Rpb24gc3RydWN0dXJlIGZvciBzcG9uc29yZWQgdHJhbnNhY3Rpb25cbiAgICAgIGNvbnN0IHByb2dyYW1tYWJsZVR4ID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHg7XG4gICAgICBwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnMubGVuZ3RoLnNob3VsZC5iZS5ncmVhdGVyVGhhbigwKTtcblxuICAgICAgLy8gVmVyaWZ5IHNwb25zb3JlZCB0cmFuc2FjdGlvbiBjaGFyYWN0ZXJpc3RpY3NcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLnNlbmRlci5zaG91bGQuZXF1YWwodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5vd25lci5zaG91bGQuZXF1YWwodGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyk7XG5cbiAgICAgIC8vIFNob3VsZCBoYXZlIHRyYW5zYWN0aW9ucyBmb3IgbWVyZ2luZy9zcGxpdHRpbmcgYW5kIHRyYW5zZmVycmluZyB3aGVuIHVzaW5nIGlucHV0T2JqZWN0c1xuICAgICAgcHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zLmxlbmd0aC5zaG91bGQuYmUuZ3JlYXRlclRoYW4oMCk7XG5cbiAgICAgIC8vIFZlcmlmeSB3ZSBoYXZlIHRyYW5zZmVyIG9wZXJhdGlvbnMgKHRoZSBleGFjdCBzdHJ1Y3R1cmUgdmFyaWVzIHdpdGggQVBJIHZlcnNpb25zKVxuICAgICAgc2hvdWxkLmV4aXN0KHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9ucyk7XG5cbiAgICAgIC8vIFZlcmlmeSBpbnB1dE9iamVjdHMgYXJlIG5vdCB1c2VkIGluIGdhcyBwYXltZW50ICh0aGV5J3JlIHNlcGFyYXRlKVxuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50LnNob3VsZC5ub3QuY29udGFpbkRlZXAoaW5wdXRPYmplY3RzKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmV4aXN0KHJhd1R4KTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eXBlb2YgcmF3VHgsICdzdHJpbmcnKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzcGxpdCBjb2luIHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIGNvbnN0IGFtb3VudCA9IDEwMDAwMDAwMDA7XG4gICAgICBjb25zdCByZWNpcGllbnRzID0gbmV3IEFycmF5KDEwMCkuZmlsbCh7IGFkZHJlc3M6IHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLCBhbW91bnQ6IGFtb3VudC50b1N0cmluZygpIH0pO1xuICAgICAgdHhCdWlsZGVyLnNlbmQocmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YSh0ZXN0RGF0YS5nYXNEYXRhKTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuICAgICAgKHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+KS5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLnBheW1lbnQhLnNob3VsZC5kZWVwRXF1YWwoXG4gICAgICAgIHRlc3REYXRhLmNvaW5zR2FzUGF5bWVudFxuICAgICAgKTtcblxuICAgICAgdHguaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICB0eC5pbnB1dHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLFxuICAgICAgICB2YWx1ZTogKGFtb3VudCAqIDEwMCkudG9TdHJpbmcoKSxcbiAgICAgICAgY29pbjogJ3RzdWknLFxuICAgICAgfSk7XG4gICAgICB0eC5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMTAwKTtcbiAgICAgIHR4Lm91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PlxuICAgICAgICBvdXRwdXQuc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgICAgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsXG4gICAgICAgICAgdmFsdWU6IGFtb3VudC50b1N0cmluZygpLFxuICAgICAgICAgIGNvaW46ICd0c3VpJyxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc3BsaXQgY29pbiB0eCB3aXRoIG1vcmUgdGhhbiAyNTUgaW5wdXQgb2JqZWN0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFtb3VudCA9IDEwMDAwMDAwMDA7XG4gICAgICBjb25zdCBudW1iZXJPZlJlY2lwaWVudHMgPSAxMDtcbiAgICAgIGNvbnN0IG51bWJlck9mUGF5bWVudE9iamVjdHMgPSAxMDAwO1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuXG4gICAgICBjb25zdCByZWNpcGllbnRzID0gbmV3IEFycmF5KG51bWJlck9mUmVjaXBpZW50cykuZmlsbCh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLFxuICAgICAgICBhbW91bnQ6IGFtb3VudC50b1N0cmluZygpLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIHBheW1lbnQ6IHRlc3REYXRhLmdlbmVyYXRlT2JqZWN0cyhudW1iZXJPZlBheW1lbnRPYmplY3RzKSxcbiAgICAgIH07XG5cbiAgICAgIHR4QnVpbGRlci5zZW5kKHJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoZ2FzRGF0YSk7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuXG4gICAgICBhc3NlcnQodHggaW5zdGFuY2VvZiBTdWlUcmFuc2FjdGlvbik7XG4gICAgICB0eC50eXBlLnNob3VsZC5lcXVhbChUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICB0eC5pbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHR4LmlucHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsXG4gICAgICAgIHZhbHVlOiAoYW1vdW50ICogMTApLnRvU3RyaW5nKCksXG4gICAgICAgIGNvaW46ICd0c3VpJyxcbiAgICAgIH0pO1xuICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEwKTtcbiAgICAgIHR4Lm91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PlxuICAgICAgICBvdXRwdXQuc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgICAgY29pbjogJ3RzdWknLFxuICAgICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLFxuICAgICAgICAgIHZhbHVlOiBhbW91bnQudG9TdHJpbmcoKSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICB0eC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbChnYXNEYXRhLm93bmVyKTtcbiAgICAgIHR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucHJpY2Uuc2hvdWxkLmVxdWFsKGdhc0RhdGEucHJpY2UpO1xuICAgICAgdHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5idWRnZXQuc2hvdWxkLmVxdWFsKGdhc0RhdGEuYnVkZ2V0KTtcbiAgICAgIHR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKE1BWF9HQVNfT0JKRUNUUyAtIDEpO1xuXG4gICAgICBjb25zdCBwcm9ncmFtbWFibGVUeCA9IHR4LnN1aVRyYW5zYWN0aW9uLnR4O1xuXG4gICAgICAvLyB0b3RhbCBvYmplY3RzIC0gb2JqZWN0cyBzZW50IGFzIGdhcyBwYXltZW50ICsgbm8uIG9mIHJlY2lwaWVudCBhbW91bnRzKHB1cmUpXG4gICAgICAvLyArIG5vLiBvZiB1bmlxdWUgcmVjaXBpZW50IGFkZHJlc3NlcyhkZS1kdXBlZCBvYmplY3RzKVxuICAgICAgcHJvZ3JhbW1hYmxlVHguaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoXG4gICAgICAgIG51bWJlck9mUGF5bWVudE9iamVjdHMgLSAoTUFYX0dBU19PQkpFQ1RTIC0gMSkgKyBudW1iZXJPZlJlY2lwaWVudHMgKyAxXG4gICAgICApO1xuICAgICAgcHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzBdLmtpbmQuc2hvdWxkLmVxdWFsKCdNZXJnZUNvaW5zJyk7XG4gICAgICBwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0uc291cmNlcy5sZW5ndGguc2hvdWxkLmVxdWFsKE1BWF9DT01NQU5EX0FSR1MgLSAxKTtcbiAgICAgIHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1sxXS5raW5kLnNob3VsZC5lcXVhbCgnTWVyZ2VDb2lucycpO1xuICAgICAgcHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzFdLnNvdXJjZXMubGVuZ3RoLnNob3VsZC5lcXVhbChcbiAgICAgICAgbnVtYmVyT2ZQYXltZW50T2JqZWN0cyAtIChNQVhfQ09NTUFORF9BUkdTIC0gMSkgLSAoTUFYX0dBU19PQkpFQ1RTIC0gMSlcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICAgIHJlYnVpbHRUeC50b0pzb24oKS5nYXNEYXRhLnBheW1lbnQubGVuZ3RoLnNob3VsZC5lcXVhbChudW1iZXJPZlBheW1lbnRPYmplY3RzKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0ZhaWwnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBmYWlsIGZvciBpbnZhbGlkIHNlbmRlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgc2hvdWxkKCgpID0+IGJ1aWxkZXIuc2VuZGVyKCdyYW5kb21TdHJpbmcnKSkudGhyb3dFcnJvcignSW52YWxpZCBvciBtaXNzaW5nIHNlbmRlciwgZ290OiByYW5kb21TdHJpbmcnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBmb3IgaW52YWxpZCBwYXlUeCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgc2hvdWxkKCgpID0+IGJ1aWxkZXIuc2VuZChbdGVzdERhdGEuaW52YWxpZFJlY2lwaWVudHNbMF1dKSkudGhyb3dFcnJvcihcbiAgICAgICAgJ0ludmFsaWQgb3IgbWlzc2luZyBhZGRyZXNzLCBnb3Q6IHJhbmRvbVN0cmluZydcbiAgICAgICk7XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5zZW5kKFt0ZXN0RGF0YS5pbnZhbGlkUmVjaXBpZW50c1sxXV0pKS50aHJvd0Vycm9yKCdJbnZhbGlkIHJlY2lwaWVudCBhbW91bnQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBmb3IgaW52YWxpZCBnYXNEYXRhJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5nYXNEYXRhKHRlc3REYXRhLmludmFsaWRHYXNPd25lcikpLnRocm93RXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIGdhcyBhZGRyZXNzICR7dGVzdERhdGEuaW52YWxpZEdhc093bmVyLm93bmVyfWBcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgZm9yIGludmFsaWQgZ2FzQnVkZ2V0JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5nYXNEYXRhKHRlc3REYXRhLmludmFsaWRHYXNCdWRnZXQpKS50aHJvd0Vycm9yKCdJbnZhbGlkIGdhcyBidWRnZXQgLTEnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBmb3IgaW52YWxpZCBnYXNQYXltZW50JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBjb25zdCBpbnZhbGlkR2FzUGF5bWVudCA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YVdpdGhvdXRHYXNQYXltZW50LFxuICAgICAgICBwYXltZW50OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgb2JqZWN0SWQ6ICcnLFxuICAgICAgICAgICAgdmVyc2lvbjogLTEsXG4gICAgICAgICAgICBkaWdlc3Q6ICcnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgICAgc2hvdWxkKCgpID0+IGJ1aWxkZXIuZ2FzRGF0YShpbnZhbGlkR2FzUGF5bWVudCkpLnRocm93RXJyb3IoJ0ludmFsaWQgcGF5bWVudCwgaW52YWxpZCBvciBtaXNzaW5nIHZlcnNpb24nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBmb3IgaW52YWxpZCBpbnB1dE9iamVjdHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIGNvbnN0IGludmFsaWRJbnB1dE9iamVjdHMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBvYmplY3RJZDogJycsXG4gICAgICAgICAgdmVyc2lvbjogLTEsXG4gICAgICAgICAgZGlnZXN0OiAnJyxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5pbnB1dE9iamVjdHMoaW52YWxpZElucHV0T2JqZWN0cykpLnRocm93RXJyb3IoXG4gICAgICAgICdJbnZhbGlkIGlucHV0IG9iamVjdCwgaW52YWxpZCBvciBtaXNzaW5nIHZlcnNpb24nXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCB0cmFuc2ZlciB3aXRoIGRpZmZlcmVudCBnYXMgb3duZXIgYnV0IG5vIGlucHV0T2JqZWN0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLCAvLyBEaWZmZXJlbnQgZnJvbSBzZW5kZXJcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7IC8vIFNlbmRlclxuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTsgLy8gR2FzIHBhaWQgYnkgc3BvbnNvclxuICAgICAgLy8gTm90ZTogTk9UIHByb3ZpZGluZyBpbnB1dE9iamVjdHMgLSBzaG91bGQgc3RpbGwgd29yayAoZmVlIHNwb25zb3JzaGlwIHdpdGhvdXQgY29pbiBzcG9uc29yc2hpcClcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBzaG91bGQubm90LmV4aXN0KHN1aVR4LnN1aVRyYW5zYWN0aW9uLmlucHV0T2JqZWN0cyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXh0cmFjdCBpbnB1dE9iamVjdHMgZnJvbSB0cmFuc2FjdGlvbiBkYXRhIHZpYSB0b0pzb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnB1dE9iamVjdHMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBvYmplY3RJZDogJzB4MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3OCcsXG4gICAgICAgICAgdmVyc2lvbjogMTAwLFxuICAgICAgICAgIGRpZ2VzdDogJzJCOFhLUUo3bWZ4UVBVV3FKSkFHanpCQXppdmtXS3EyY0VhM1c4TEx6MXlCJyxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgICBvd25lcjogdGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcywgLy8gRGlmZmVyZW50IGZyb20gc2VuZGVyXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTtcbiAgICAgIHR4QnVpbGRlci5pbnB1dE9iamVjdHMoaW5wdXRPYmplY3RzKTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcblxuICAgICAgLy8gVGVzdCB0aGF0IHRvSnNvbiBleHRyYWN0cyBpbnB1dE9iamVjdHMgZnJvbSB0cmFuc2FjdGlvbiBzdHJ1Y3R1cmVcbiAgICAgIGNvbnN0IHR4RGF0YSA9ICh0eCBhcyBhbnkpLnRvSnNvbigpO1xuICAgICAgc2hvdWxkLmV4aXN0KHR4RGF0YS5pbnB1dE9iamVjdHMpO1xuXG4gICAgICAvLyBUaGUgdG9Kc29uIHNob3VsZCBleHRyYWN0IHRoZSBpbnB1dE9iamVjdHMgZnJvbSB0aGUgdHJhbnNhY3Rpb24gc3RydWN0dXJlXG4gICAgICAvLyBUaGlzIHRlc3RzIG91ciBuZXcgZ2V0SW5wdXRPYmplY3RzRnJvbVR4IG1ldGhvZFxuICAgICAgc2hvdWxkLmV4aXN0KHR4RGF0YS5pbnB1dE9iamVjdHMpO1xuICAgICAgQXJyYXkuaXNBcnJheSh0eERhdGEuaW5wdXRPYmplY3RzKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdmdW5kc0luQWRkcmVzc0JhbGFuY2UnLCAoKSA9PiB7XG4gICAgY29uc3QgRlVORFNfSU5fQUREUkVTU19CQUxBTkNFID0gJzUwMDAwMDAwMDAnOyAvLyA1IFNVSVxuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHNlbGYtcGF5IHRyYW5zZmVyIHVzaW5nIG9ubHkgYWRkcmVzcyBiYWxhbmNlIChlbXB0eSBwYXltZW50KScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGdhc0RhdGFOb1BheW1lbnQgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGFXaXRob3V0R2FzUGF5bWVudCxcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShnYXNEYXRhTm9QYXltZW50KTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLnBheW1lbnQubGVuZ3RoLnNob3VsZC5lcXVhbCgwKTtcblxuICAgICAgLy8gU2VsZi1wYXkgcGF0aDogU3BsaXRDb2lucyhHYXNDb2luLCBbYW1vdW50XSkg4oCUIG5vIE1vdmVDYWxsIG5lZWRlZFxuICAgICAgY29uc3QgcHJvZ3JhbW1hYmxlVHggPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eDtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIC8vIFJvdW5kLXRyaXA6IHJlYnVpbGQgZnJvbSByYXdcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzZWxmLXBheSB0cmFuc2ZlciB3aXRoIGNvaW4gb2JqZWN0cyArIGFkZHJlc3MgYmFsYW5jZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHRlc3REYXRhLmdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShGVU5EU19JTl9BRERSRVNTX0JBTEFOQ0UpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcblxuICAgICAgLy8gU2VsZi1wYXkgcGF0aDogU3BsaXRDb2lucyhHYXNDb2luKSDigJQgcHJvdG9jb2wgbWVyZ2VzIGNvaW4gb2JqZWN0cyArIGFkZHJlc3MgYmFsYW5jZSBhdXRvbWF0aWNhbGx5XG4gICAgICBjb25zdCBwcm9ncmFtbWFibGVUeCA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4O1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzcG9uc29yZWQgdHJhbnNmZXIgd2l0aCBjb2luIG9iamVjdHMgKyBhZGRyZXNzIGJhbGFuY2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnB1dE9iamVjdHMgPSB0ZXN0RGF0YS5nZW5lcmF0ZU9iamVjdHMoMik7XG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgICBvd25lcjogdGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmlucHV0T2JqZWN0cyhpbnB1dE9iamVjdHMpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShGVU5EU19JTl9BRERSRVNTX0JBTEFOQ0UpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MpO1xuXG4gICAgICAvLyBTcG9uc29yZWQgcGF0aDogTW92ZUNhbGwocmVkZWVtX2Z1bmRzKSArIE1lcmdlQ29pbnMgKyBTcGxpdENvaW5zXG4gICAgICBjb25zdCBwcm9ncmFtbWFibGVUeCA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4O1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdNb3ZlQ2FsbCcpO1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICAocHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzFdIGFzIGFueSkua2luZC5zaG91bGQuZXF1YWwoJ01lcmdlQ29pbnMnKTtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMl0gYXMgYW55KS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIC8vIFJvdW5kLXRyaXBcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzcG9uc29yZWQgdHJhbnNmZXIgd2l0aCBhZGRyZXNzIGJhbGFuY2Ugb25seSAobm8gY29pbiBpbnB1dE9iamVjdHMpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIC8vIFBhdGggMWI6IHdpdGhkcmF3YWwg4oaSIHJlZGVlbV9mdW5kcyDihpIgU3BsaXRDb2lucyhhZGRyQ29pbikg4oaSIFRyYW5zZmVyT2JqZWN0c1xuICAgICAgLy8gU3BvbnNvcidzIGdhcyBjb2lucyByZW1haW4gaW4gZ2FzRGF0YS5wYXltZW50OyB0eC5nYXMgaXMgTk9UIHVzZWQgZm9yIHRoZSB0cmFuc2ZlciBhbW91bnQuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5vd25lci5zaG91bGQuZXF1YWwodGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyk7XG4gICAgICBjb25zdCBwcm9ncmFtbWFibGVUeCA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4O1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdNb3ZlQ2FsbCcpO1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICAocHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzFdIGFzIGFueSkua2luZC5zaG91bGQuZXF1YWwoJ1NwbGl0Q29pbnMnKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICAvLyBSb3VuZC10cmlwOiByZWJ1aWxkIGZyb20gcmF3XG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIFBhdGggMWIgc2VuZC1hbGw6IHNwb25zb3JlZCBhZGRyLWJhbGFuY2Utb25seSwgbm8gY2hhbmdlIChNZXJnZUNvaW5zIGNvbnN1bWVzIGFkZHJDb2luKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFJlcHJvZHVjZXMgdGhlIHJlYWwgb24tY2hhaW4gZmFpbHVyZTogVW51c2VkVmFsdWVXaXRob3V0RHJvcCB7IHJlc3VsdF9pZHg6IDAgfVxuICAgICAgLy8gT2NjdXJzIHdoZW4gcmVkZWVtX2Z1bmRzIHJldHVybnMgYWRkckNvaW4sIFNwbGl0Q29pbnMgZHJhaW5zIGl0IGNvbXBsZXRlbHksIGFuZCB0aGVcbiAgICAgIC8vIDAtYmFsYW5jZSBzb3VyY2UgY29pbiBpcyBuZXZlciBjb25zdW1lZC4gIEZpeDogTWVyZ2VDb2lucyhnYXMsIFthZGRyQ29pbl0pIGF0IHRoZSBlbmQuXG4gICAgICBjb25zdCBTRU5EX0FNT1VOVCA9ICcxMDAwMDAwJzsgLy8gMC4wMDEgU1VJIOKAlCBzYW1lIGFzIHRoZSBmYWlsaW5nIHR4XG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgICBvd25lcjogdGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiB0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MsIGFtb3VudDogU0VORF9BTU9VTlQgfV0pO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoc3BvbnNvcmVkR2FzRGF0YSk7XG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKFNFTkRfQU1PVU5UKTsgLy8gc2VuZC1hbGw6IGJhbGFuY2UgPT0gcmVjaXBpZW50IGFtb3VudFxuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIGNvbnN0IGNtZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG5cbiAgICAgIC8vIEV4cGVjdGVkIGNvbW1hbmQgc2VxdWVuY2UgZm9yIFBhdGggMWIgc2VuZC1hbGw6XG4gICAgICAvLyAgIDA6IE1vdmVDYWxsIChyZWRlZW1fZnVuZHMpICAgICDigJQgd2l0aGRyYXcgYWRkckNvaW5cbiAgICAgIC8vICAgMTogU3BsaXRDb2lucyhhZGRyQ29pbikgICAgICAgIOKAlCBzcGxpdCByZWNpcGllbnQgYW1vdW50IG9mZiBhZGRyQ29pblxuICAgICAgLy8gICAyOiBUcmFuc2Zlck9iamVjdHMoW3NwbGl0XSkgICAg4oCUIHNlbmQgdG8gcmVjaXBpZW50XG4gICAgICAvLyAgIDM6IE1lcmdlQ29pbnMoZ2FzLCBbYWRkckNvaW5dKSDigJQgY29uc3VtZSB0aGUgbm93LXplcm8tYmFsYW5jZSBhZGRyQ29pblxuICAgICAgY21kc1swXS5raW5kLnNob3VsZC5lcXVhbCgnTW92ZUNhbGwnKTtcbiAgICAgIGNtZHNbMF0udGFyZ2V0LnNob3VsZC5lcXVhbCgnMHgyOjpjb2luOjpyZWRlZW1fZnVuZHMnKTtcbiAgICAgIGNtZHNbMV0ua2luZC5zaG91bGQuZXF1YWwoJ1NwbGl0Q29pbnMnKTtcbiAgICAgIGNtZHNbMl0ua2luZC5zaG91bGQuZXF1YWwoJ1RyYW5zZmVyT2JqZWN0cycpO1xuICAgICAgY21kc1szXS5raW5kLnNob3VsZC5lcXVhbCgnTWVyZ2VDb2lucycsICdleHBlY3RlZCBNZXJnZUNvaW5zIHRvIGNvbnN1bWUgMC1iYWxhbmNlIGFkZHJDb2luIGFmdGVyIHNlbmQtYWxsJyk7XG5cbiAgICAgIC8vIFJlY2lwaWVudCBwYXJzaW5nIG11c3Qgbm90IGJlIGFmZmVjdGVkIGJ5IHRoZSB0cmFpbGluZyBNZXJnZUNvaW5zXG4gICAgICBjb25zdCByZWNpcGllbnRzID0gdXRpbHMuZ2V0UmVjaXBpZW50cyhzdWlUeC5zdWlUcmFuc2FjdGlvbik7XG4gICAgICByZWNpcGllbnRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICByZWNpcGllbnRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcyk7XG4gICAgICByZWNpcGllbnRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoU0VORF9BTU9VTlQpO1xuXG4gICAgICAvLyBSb3VuZC10cmlwXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIFBhdGggMWIgd2l0aCBjaGFuZ2U6IHNwb25zb3JlZCBhZGRyLWJhbGFuY2Utb25seSwgZXhjZXNzIHJldHVybmVkIHRvIHNlbmRlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIGZ1bmRzSW5BZGRyZXNzQmFsYW5jZSBleGNlZWRzIHRoZSB0b3RhbCByZWNpcGllbnQgYW1vdW50IOKGkiBjaGFuZ2UgbXVzdCBiZSByZXR1cm5lZCB0b1xuICAgICAgLy8gdGhlIHNlbmRlciBhcyBhbiBleHRyYSBUcmFuc2Zlck9iamVjdHMoW2FkZHJDb2luXSwgc2VuZGVyKS4gIFRoZSB0cmFuc2FjdGlvbiBwYXJzZXIgbXVzdFxuICAgICAgLy8gc2tpcCB0aGlzIGNoYW5nZSB0cmFuc2ZlciBhbmQgb25seSByZXBvcnQgYWN0dWFsIHJlY2lwaWVudHMuXG4gICAgICBjb25zdCBTRU5EX0FNT1VOVCA9ICcxMDAnOyAvLyBlYWNoIG9mIHRoZSB0d28gdGVzdERhdGEucmVjaXBpZW50cyBnZXRzIDEwMFxuICAgICAgY29uc3QgRVhDRVNTID0gJzk5OTk5MDAnOyAvLyBmdW5kc0luQWRkcmVzc0JhbGFuY2UgPSAxMF8wMDBfMDAwLCB0b3RhbCBzZW5kID0gMjAwXG4gICAgICBjb25zdCBGVU5EU19CQUxBTkNFID0gKE51bWJlcihTRU5EX0FNT1VOVCkgKiB0ZXN0RGF0YS5yZWNpcGllbnRzLmxlbmd0aCArIE51bWJlcihFWENFU1MpKS50b1N0cmluZygpO1xuXG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgICBvd25lcjogdGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTsgLy8gMiByZWNpcGllbnRzIMOXIDEwMCBNSVNUID0gMjAwIE1JU1QgdG90YWxcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShGVU5EU19CQUxBTkNFKTsgLy8gMTBfMDAwXzAwMCA+IDIwMCDihpIgaGFzIGNoYW5nZVxuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIGNvbnN0IGNtZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG5cbiAgICAgIC8vIEV4cGVjdGVkIHNlcXVlbmNlIGZvciBQYXRoIDFiIHdpdGggY2hhbmdlICgyIHJlY2lwaWVudHMpOlxuICAgICAgLy8gICAwOiBNb3ZlQ2FsbCAocmVkZWVtX2Z1bmRzKVxuICAgICAgLy8gICAxOiBTcGxpdENvaW5zICDigJQgIHJlY2lwaWVudCAwXG4gICAgICAvLyAgIDI6IFRyYW5zZmVyT2JqZWN0cyAg4oCUICByZWNpcGllbnQgMFxuICAgICAgLy8gICAzOiBTcGxpdENvaW5zICDigJQgIHJlY2lwaWVudCAxXG4gICAgICAvLyAgIDQ6IFRyYW5zZmVyT2JqZWN0cyAg4oCUICByZWNpcGllbnQgMVxuICAgICAgLy8gICA1OiBUcmFuc2Zlck9iamVjdHMoW2FkZHJDb2luXSwgc2VuZGVyKSAg4oCUICBjaGFuZ2UgYmFjayB0byBzZW5kZXJcbiAgICAgIGNtZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJyk7XG4gICAgICBjbWRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICBjb25zdCBsYXN0Q21kID0gY21kc1tjbWRzLmxlbmd0aCAtIDFdO1xuICAgICAgbGFzdENtZC5raW5kLnNob3VsZC5lcXVhbCgnVHJhbnNmZXJPYmplY3RzJywgJ2xhc3QgY29tbWFuZCBtdXN0IGJlIHRoZSBjaGFuZ2UgdHJhbnNmZXInKTtcblxuICAgICAgLy8gVGhlIGxhc3QgVHJhbnNmZXJPYmplY3RzIHJldHVybnMgY2hhbmdlIHRvIHRoZSAqc2VuZGVyKiwgbm90IGEgcmVjaXBpZW50XG4gICAgICBjb25zdCBjaGFuZ2VBZGRySW5wdXQgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC5pbnB1dHNbbGFzdENtZC5hZGRyZXNzLmluZGV4XSBhcyBhbnk7XG4gICAgICBjb25zdCBjaGFuZ2VBZGRyID0gdXRpbHMuZ2V0QWRkcmVzcyhjaGFuZ2VBZGRySW5wdXQpO1xuICAgICAgY2hhbmdlQWRkci5zaG91bGQuZXF1YWwodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsICdjaGFuZ2UgbXVzdCBnbyBiYWNrIHRvIHNlbmRlcicpO1xuXG4gICAgICAvLyBQYXJzZXIgbXVzdCByZXR1cm4gb25seSB0aGUgYWN0dWFsIHJlY2lwaWVudHMsIG5vdCB0aGUgY2hhbmdlIHRyYW5zZmVyXG4gICAgICBjb25zdCByZWNpcGllbnRzID0gdXRpbHMuZ2V0UmVjaXBpZW50cyhzdWlUeC5zdWlUcmFuc2FjdGlvbik7XG4gICAgICByZWNpcGllbnRzLmxlbmd0aC5zaG91bGQuZXF1YWwodGVzdERhdGEucmVjaXBpZW50cy5sZW5ndGgpO1xuICAgICAgcmVjaXBpZW50c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MpO1xuICAgICAgcmVjaXBpZW50c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKFNFTkRfQU1PVU5UKTtcbiAgICAgIHJlY2lwaWVudHNbMV0uYWRkcmVzcy5zaG91bGQuZXF1YWwodGVzdERhdGEucmVjaXBpZW50c1sxXS5hZGRyZXNzKTtcbiAgICAgIHJlY2lwaWVudHNbMV0uYW1vdW50LnNob3VsZC5lcXVhbChTRU5EX0FNT1VOVCk7XG5cbiAgICAgIC8vIFJvdW5kLXRyaXBcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzcG9uc29yZWQgdHggZ2FzIHBhaWQgZnJvbSBzcG9uc29yIGFkZHJlc3MgYmFsYW5jZSAoZW1wdHkgcGF5bWVudCknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnB1dE9iamVjdHMgPSB0ZXN0RGF0YS5nZW5lcmF0ZU9iamVjdHMoMSk7XG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhTm9QYXltZW50ID0ge1xuICAgICAgICBwYXltZW50OiBbXSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgICAgIHByaWNlOiB0ZXN0RGF0YS5nYXNEYXRhLnByaWNlLFxuICAgICAgICBidWRnZXQ6IHRlc3REYXRhLmdhc0RhdGEuYnVkZ2V0LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoc3BvbnNvcmVkR2FzRGF0YU5vUGF5bWVudCk7XG4gICAgICB0eEJ1aWxkZXIuaW5wdXRPYmplY3RzKGlucHV0T2JqZWN0cyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5vd25lci5zaG91bGQuZXF1YWwodGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyk7XG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLnBheW1lbnQubGVuZ3RoLnNob3VsZC5lcXVhbCgwKTtcblxuICAgICAgLy8gU3BvbnNvcmVkIHBhdGggd2l0aCBjb2luIG9iamVjdHMsIG5vIGFkZHJlc3MgYmFsYW5jZSB3aXRoZHJhd2FsXG4gICAgICBjb25zdCBwcm9ncmFtbWFibGVUeCA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4O1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcm91bmQtdHJpcCBhIHNlbGYtcGF5IHRyYW5zZmVyIHdpdGggRXBvY2ggZXhwaXJhdGlvbiB2aWEgZnJvbUJ5dGVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gUmVncmVzc2lvbiB0ZXN0IGZvciB0aGUgQmlnSW50IHJvdW5kLXRyaXAgYnVnOlxuICAgICAgLy8gQkNTLlU2NCBkZXNlcmlhbGl6ZXMgdTY0IGFzIEJpZ0ludCwgYnV0IHRoZSBwcmV2aW91cyBzdXBlcnN0cnVjdCBzY2hlbWEgdXNlZCBpbnRlZ2VyKClcbiAgICAgIC8vIHdoaWNoIHJlamVjdGVkIEJpZ0ludCwgY2F1c2luZyBmcm9tQnl0ZXMoKSB0byB0aHJvdyBhIFN0cnVjdEVycm9yIGF0IFwiZXhwaXJhdGlvblwiLlxuICAgICAgLy8gU3RyaW5nRW5jb2RlZEJpZ2ludCBub3cgYWNjZXB0cyBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQsIGZpeGluZyB0aGUgcm91bmQtdHJpcC5cbiAgICAgIGNvbnN0IGdhc0RhdGFOb1BheW1lbnQgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGFXaXRob3V0R2FzUGF5bWVudCxcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShnYXNEYXRhTm9QYXltZW50KTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcbiAgICAgIHR4QnVpbGRlci5leHBpcmF0aW9uKHsgRXBvY2g6IDMyNCB9KTsgLy8gbnVtYmVyIGlucHV0XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIC8vIGZyb21CeXRlcyBtdXN0IG5vdCB0aHJvdyBTdHJ1Y3RFcnJvciDigJQgdGhpcyB3YXMgdGhlIGZhaWxpbmcgY2FzZSBiZWZvcmUgdGhlIGZpeFxuICAgICAgc2hvdWxkLmRvZXNOb3RUaHJvdygoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICAgIHNob3VsZC5leGlzdChyZWJ1aWxkZXIpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIEZ1bGwgcm91bmQtdHJpcDogcmVidWlsdCB0eCBtdXN0IHNlcmlhbGl6ZSBpZGVudGljYWxseVxuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuXG4gICAgICAvLyBFcG9jaCB2YWx1ZSBtdXN0IHN1cnZpdmUgdGhlIHJvdW5kLXRyaXAgcmVnYXJkbGVzcyBvZiBCaWdJbnQvbnVtYmVyIHJlcHJlc2VudGF0aW9uXG4gICAgICBjb25zdCByZWJ1aWx0SnNvbiA9IHJlYnVpbHRUeC50b0pzb24oKTtcbiAgICAgIGNvbnN0IGVwb2NoVmFsID0gKHJlYnVpbHRKc29uLmV4cGlyYXRpb24gYXMgYW55KT8uRXBvY2g7XG4gICAgICBzaG91bGQuZXhpc3QoZXBvY2hWYWwpO1xuICAgICAgTnVtYmVyKGVwb2NoVmFsKS5zaG91bGQuZXF1YWwoMzI0KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcm91bmQtdHJpcCBhIHNlbGYtcGF5IHRyYW5zZmVyIHdpdGggVmFsaWREdXJpbmcgZXhwaXJhdGlvbiB2aWEgZnJvbUJ5dGVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVmVyaWZpZXMgdGhlIGZ1bGwgNi1maWVsZCBWYWxpZER1cmluZ0V4cGlyYXRpb24gQkNTIHNjaGVtYTpcbiAgICAgIC8vICAgbWluRXBvY2gvbWF4RXBvY2ggYXMgT3B0aW9uPHU2ND4sIG1pblRpbWVzdGFtcC9tYXhUaW1lc3RhbXAgYXMgT3B0aW9uPHU2ND4gKE5vbmUpLFxuICAgICAgLy8gICBjaGFpbiBhcyAzMi1ieXRlIEJhc2U1OCBPYmplY3REaWdlc3QsIG5vbmNlIGFzIHUzMi5cbiAgICAgIC8vIFVzZXMgYSByZWFsIG1haW5uZXQgZ2VuZXNpcyBjaGVja3BvaW50IGRpZ2VzdCAoMzIgYnl0ZXMsIEJhc2U1OCkuXG4gICAgICBjb25zdCBHRU5FU0lTX0NIQUlOX0lEID0gJ0dBRnBDQ2NSQ3hUZEZmVUVNYlFia0xCYVp5MlJOaUdBZnZGQmhNTnBxMmtUJztcbiAgICAgIGNvbnN0IEZVTkRTX0lOX0FERFJFU1NfQkFMQU5DRSA9ICc1MDAwMDAwMDAwJztcbiAgICAgIGNvbnN0IGdhc0RhdGFOb1BheW1lbnQgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGFXaXRob3V0R2FzUGF5bWVudCxcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShnYXNEYXRhTm9QYXltZW50KTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcbiAgICAgIHR4QnVpbGRlci5leHBpcmF0aW9uKHtcbiAgICAgICAgVmFsaWREdXJpbmc6IHtcbiAgICAgICAgICBtaW5FcG9jaDogeyBTb21lOiA1MDAgfSxcbiAgICAgICAgICBtYXhFcG9jaDogeyBTb21lOiA1MDEgfSxcbiAgICAgICAgICBtaW5UaW1lc3RhbXA6IHsgTm9uZTogbnVsbCB9LFxuICAgICAgICAgIG1heFRpbWVzdGFtcDogeyBOb25lOiBudWxsIH0sXG4gICAgICAgICAgY2hhaW46IEdFTkVTSVNfQ0hBSU5fSUQsXG4gICAgICAgICAgbm9uY2U6IDB4ZGVhZGJlZWYsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcblxuICAgICAgLy8gZnJvbUJ5dGVzIG11c3Qgbm90IHRocm93IOKAlCBWYWxpZER1cmluZyBmaWVsZHMgbXVzdCBzdXJ2aXZlIGRlc2VyaWFsaXphdGlvblxuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG5cbiAgICAgIC8vIEJDUyByb3VuZC10cmlwOiBzZXJpYWxpemVkIGJ5dGVzIG11c3QgYmUgaWRlbnRpY2FsXG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuXG4gICAgICAvLyBBbGwgVmFsaWREdXJpbmcgZmllbGRzIG11c3Qgc3Vydml2ZSB0aGUgcm91bmQtdHJpcFxuICAgICAgY29uc3QgZXhwaXJhdGlvbiA9IChyZWJ1aWx0VHgudG9Kc29uKCkuZXhwaXJhdGlvbiBhcyBhbnkpPy5WYWxpZER1cmluZztcbiAgICAgIHNob3VsZC5leGlzdChleHBpcmF0aW9uKTtcbiAgICAgIE51bWJlcihleHBpcmF0aW9uLm1pbkVwb2NoPy5Tb21lID8/IGV4cGlyYXRpb24ubWluRXBvY2gpLnNob3VsZC5lcXVhbCg1MDApO1xuICAgICAgTnVtYmVyKGV4cGlyYXRpb24ubWF4RXBvY2g/LlNvbWUgPz8gZXhwaXJhdGlvbi5tYXhFcG9jaCkuc2hvdWxkLmVxdWFsKDUwMSk7XG4gICAgICBleHBpcmF0aW9uLmNoYWluLnNob3VsZC5lcXVhbChHRU5FU0lTX0NIQUlOX0lEKTtcbiAgICAgIE51bWJlcihleHBpcmF0aW9uLm5vbmNlKS5zaG91bGQuZXF1YWwoMHhkZWFkYmVlZik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdCYWxhbmNlV2l0aGRyYXdhbCBCQ1MgZW5jb2RpbmcgKEZ1bmRzV2l0aGRyYXdhbCBmb3JtYXQpJywgKCkgPT4ge1xuICAgIGNvbnN0IEFNT1VOVCA9ICcxMDAwMDAwMDAnOyAvLyAwLjEgU1VJIGluIE1JU1RcbiAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLFxuICAgIH07XG5cbiAgICBhc3luYyBmdW5jdGlvbiBidWlsZFNwb25zb3JlZFR4V2l0aEFkZHJlc3NCYWxhbmNlKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKFt7IGFkZHJlc3M6IHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcywgYW1vdW50OiBBTU9VTlQgfV0pO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoc3BvbnNvcmVkR2FzRGF0YSk7XG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKEFNT1VOVCk7XG4gICAgICByZXR1cm4gdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgfVxuXG4gICAgaXQoJ3Nob3VsZCBlbmNvZGUgQmFsYW5jZVdpdGhkcmF3YWwgaW5wdXQgd2l0aCBGdW5kc1dpdGhkcmF3YWwgc3RydWN0dXJlIChyZXNlcnZhdGlvbi90eXBlQXJnL3dpdGhkcmF3RnJvbSknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IGJ1aWxkU3BvbnNvcmVkVHhXaXRoQWRkcmVzc0JhbGFuY2UoKTtcbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBjb25zdCBpbnB1dHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC5pbnB1dHMgYXMgYW55W107XG5cbiAgICAgIGNvbnN0IGJ3SW5wdXQgPSBpbnB1dHMuZmluZChcbiAgICAgICAgKGlucCkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQuZXhpc3QoYndJbnB1dCwgJ0JhbGFuY2VXaXRoZHJhd2FsIGlucHV0IG11c3QgYmUgcHJlc2VudCcpO1xuXG4gICAgICBjb25zdCBidyA9IGJ3SW5wdXQuQmFsYW5jZVdpdGhkcmF3YWwgPz8gYndJbnB1dC52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWw7XG5cbiAgICAgIHNob3VsZC5leGlzdChidy5yZXNlcnZhdGlvbiwgJ3Jlc2VydmF0aW9uIGZpZWxkIG11c3QgZXhpc3QnKTtcbiAgICAgIHNob3VsZC5leGlzdChidy5yZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQsICdyZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQgbXVzdCBleGlzdCcpO1xuICAgICAgYncucmVzZXJ2YXRpb24uTWF4QW1vdW50VTY0LnRvU3RyaW5nKCkuc2hvdWxkLmVxdWFsKEFNT1VOVCk7XG5cbiAgICAgIHNob3VsZC5leGlzdChidy50eXBlQXJnLCAndHlwZUFyZyBmaWVsZCBtdXN0IGV4aXN0Jyk7XG4gICAgICBzaG91bGQuZXhpc3QoYncudHlwZUFyZy5CYWxhbmNlLCAndHlwZUFyZy5CYWxhbmNlIG11c3QgZXhpc3QnKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KGJ3LndpdGhkcmF3RnJvbSwgJ3dpdGhkcmF3RnJvbSBmaWVsZCBtdXN0IGV4aXN0Jyk7XG4gICAgICBzaG91bGQuZXhpc3QoXG4gICAgICAgIGJ3LndpdGhkcmF3RnJvbS5TZW5kZXIgIT09IHVuZGVmaW5lZCB8fCBidy53aXRoZHJhd0Zyb20uU3BvbnNvciAhPT0gdW5kZWZpbmVkLFxuICAgICAgICAnd2l0aGRyYXdGcm9tIG11c3QgYmUgU2VuZGVyIG9yIFNwb25zb3InXG4gICAgICApO1xuXG4gICAgICAvLyBPbGQgZm9ybWF0IGZpZWxkcyBtdXN0IE5PVCBleGlzdCBkaXJlY3RseSBvbiBid1xuICAgICAgc2hvdWxkLm5vdC5leGlzdChidy5hbW91bnQsICdvbGQgXCJhbW91bnRcIiBmaWVsZCBtdXN0IG5vdCBleGlzdCBvbiBCYWxhbmNlV2l0aGRyYXdhbCcpO1xuICAgICAgc2hvdWxkLm5vdC5leGlzdChidy50eXBlXywgJ29sZCBcInR5cGVfXCIgZmllbGQgbXVzdCBub3QgZXhpc3Qgb24gQmFsYW5jZVdpdGhkcmF3YWwnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcHJvZHVjZSBCQ1MgYnl0ZXMgdGhhdCBkZWNvZGUgYmFjayB0byBGdW5kc1dpdGhkcmF3YWwgd2l0aCBjb3JyZWN0IGFtb3VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgYnVpbGRTcG9uc29yZWRUeFdpdGhBZGRyZXNzQmFsYW5jZSgpO1xuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSBTdWlUcmFuc2FjdGlvbi5kZXNlcmlhbGl6ZVN1aVRyYW5zYWN0aW9uKHJhd1R4KTtcbiAgICAgIGNvbnN0IGlucHV0cyA9IGRlc2VyaWFsaXplZC50eC5pbnB1dHMgYXMgYW55W107XG5cbiAgICAgIGNvbnN0IGJ3SW5wdXQgPSBpbnB1dHMuZmluZChcbiAgICAgICAgKGlucCkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQuZXhpc3QoYndJbnB1dCwgJ0JhbGFuY2VXaXRoZHJhd2FsIG11c3QgYmUgcHJlc2VudCBpbiBkZXNlcmlhbGl6ZWQgaW5wdXRzJyk7XG5cbiAgICAgIGNvbnN0IGJ3ID0gYndJbnB1dC5CYWxhbmNlV2l0aGRyYXdhbCA/PyBid0lucHV0LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbDtcblxuICAgICAgLy8gRnVuZHNXaXRoZHJhd2FsIHN0cnVjdHVyZSAobm90IG9sZCB7YW1vdW50LCB0eXBlX30pXG4gICAgICBzaG91bGQuZXhpc3QoYncucmVzZXJ2YXRpb24sICdyZXNlcnZhdGlvbiBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXAnKTtcbiAgICAgIHNob3VsZC5leGlzdChidy5yZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQsICdNYXhBbW91bnRVNjQgbXVzdCBzdXJ2aXZlIEJDUyByb3VuZC10cmlwJyk7XG4gICAgICBidy5yZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQudG9TdHJpbmcoKS5zaG91bGQuZXF1YWwoQU1PVU5UKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnR5cGVBcmcsICd0eXBlQXJnIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCcpO1xuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnR5cGVBcmcuQmFsYW5jZSwgJ3R5cGVBcmcuQmFsYW5jZSBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXAnKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KGJ3LndpdGhkcmF3RnJvbSwgJ3dpdGhkcmF3RnJvbSBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXAnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2VyaWFsaXplIHRvSnNvbigpIHdpdGhvdXQgYSBCaWdJbnQgcmVwbGFjZXIgKG5vIFR5cGVFcnJvciknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IGJ1aWxkU3BvbnNvcmVkVHhXaXRoQWRkcmVzc0JhbGFuY2UoKTtcbiAgICAgIHNob3VsZC5kb2VzTm90VGhyb3coXG4gICAgICAgICgpID0+IEpTT04uc3RyaW5naWZ5KHR4LnRvSnNvbigpKSxcbiAgICAgICAgJ0pTT04uc3RyaW5naWZ5KHR4LnRvSnNvbigpKSBtdXN0IG5vdCB0aHJvdyDigJQgQmFsYW5jZVdpdGhkcmF3YWwgYW1vdW50IG11c3Qgbm90IGJlIHN0b3JlZCBhcyBCaWdJbnQnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcmVzZXJ2ZSBmdW5kc0luQWRkcmVzc0JhbGFuY2UgYW1vdW50IHRocm91Z2ggZnVsbCByb3VuZC10cmlwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHggPSBhd2FpdCBidWlsZFNwb25zb3JlZFR4V2l0aEFkZHJlc3NCYWxhbmNlKCk7XG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuXG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHJlYnVpbHRUeCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIGNvbnN0IGlucHV0cyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LmlucHV0cyBhcyBhbnlbXTtcbiAgICAgIGNvbnN0IGJ3SW5wdXQgPSBpbnB1dHMuZmluZChcbiAgICAgICAgKGlucCkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQuZXhpc3QoYndJbnB1dCk7XG4gICAgICBjb25zdCBidyA9IGJ3SW5wdXQuQmFsYW5jZVdpdGhkcmF3YWwgPz8gYndJbnB1dC52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWw7XG4gICAgICBidy5yZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQudG9TdHJpbmcoKS5zaG91bGQuZXF1YWwoQU1PVU5UKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZW5jb2RlIGdhcy1mcm9tLWFkZHJlc3MtYmFsYW5jZSAoc2VsZi1wYXksIGVtcHR5IHBheW1lbnQpIHdpdGggbm8gRnVuZHNXaXRoZHJhd2FsIGlucHV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gV2hlbiBnYXNEYXRhLnBheW1lbnQ9W10gYW5kIHNlbmRlcj09PWdhc0RhdGEub3duZXIsIHRoZSBTdWkgcnVudGltZSBhdXRvbWF0aWNhbGx5XG4gICAgICAvLyB1c2VzIGFkZHJlc3MgYmFsYW5jZSB0byBmdW5kIGJvdGggZ2FzIGFuZCB0aGUgdHJhbnNmZXIgdmlhIEdhc0NvaW4uXG4gICAgICAvLyBObyBCYWxhbmNlV2l0aGRyYXdhbCBDYWxsQXJnIGlzIG5lZWRlZCDigJQgdGhlIHJ1bnRpbWUgaGFuZGxlcyBpdCBpbXBsaWNpdGx5LlxuICAgICAgY29uc3Qgc2VsZlBheU5vUGF5bWVudCA9IHsgLi4udGVzdERhdGEuZ2FzRGF0YVdpdGhvdXRHYXNQYXltZW50LCBwYXltZW50OiBbXSB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQoW3sgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLCBhbW91bnQ6IEFNT1VOVCB9XSk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzZWxmUGF5Tm9QYXltZW50KTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoQU1PVU5UKTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG5cbiAgICAgIC8vIEdhcyBvd25lciBtdXN0IGVxdWFsIHNlbmRlciAoc2VsZi1wYXkpXG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICAvLyBQYXltZW50IG11c3QgYmUgZW1wdHkg4oCUIGdhcyBmdW5kZWQgZnJvbSBhZGRyZXNzIGJhbGFuY2UgYnkgdGhlIHJ1bnRpbWVcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICAvLyBObyBCYWxhbmNlV2l0aGRyYXdhbCBpbnB1dCDigJQgcnVudGltZSBoYW5kbGVzIGFkZHJlc3MgYmFsYW5jZSBhdXRvbWF0aWNhbGx5XG4gICAgICBjb25zdCBpbnB1dHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC5pbnB1dHMgYXMgYW55W107XG4gICAgICBjb25zdCBid0lucHV0ID0gaW5wdXRzLmZpbmQoXG4gICAgICAgIChpbnApID0+IGlucD8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZCB8fCBpbnA/LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkXG4gICAgICApO1xuICAgICAgc2hvdWxkLm5vdC5leGlzdChid0lucHV0LCAnc2VsZi1wYXkgbXVzdCBOT1QgaGF2ZSBhIEJhbGFuY2VXaXRoZHJhd2FsIGlucHV0IOKAlCBydW50aW1lIGhhbmRsZXMgaXQnKTtcblxuICAgICAgLy8gRmlyc3QgY29tbWFuZCBtdXN0IGJlIFNwbGl0Q29pbnMoR2FzQ29pbikg4oCUIG5vIHJlZGVlbV9mdW5kcyBuZWVkZWRcbiAgICAgIGNvbnN0IGNvbW1hbmRzID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHgudHJhbnNhY3Rpb25zIGFzIGFueVtdO1xuICAgICAgY29tbWFuZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ1NwbGl0Q29pbnMnKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSBTdWlUcmFuc2FjdGlvbi5kZXNlcmlhbGl6ZVN1aVRyYW5zYWN0aW9uKHJhd1R4KTtcbiAgICAgIGRlc2VyaWFsaXplZC5zZW5kZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIGRlc2VyaWFsaXplZC5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICBkZXNlcmlhbGl6ZWQuZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIC8vIE5vIEZ1bmRzV2l0aGRyYXdhbCBpbiBkZWNvZGVkIGlucHV0cyDigJQgb25seSBQdXJlIGFyZ3NcbiAgICAgIGNvbnN0IGRlY29kZWRJbnB1dHMgPSBkZXNlcmlhbGl6ZWQudHguaW5wdXRzIGFzIGFueVtdO1xuICAgICAgZGVjb2RlZElucHV0c1xuICAgICAgICAuZXZlcnkoKGlucDogYW55KSA9PiBpbnA/LkJhbGFuY2VXaXRoZHJhd2FsID09PSB1bmRlZmluZWQgJiYgaW5wPy52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWwgPT09IHVuZGVmaW5lZClcbiAgICAgICAgLnNob3VsZC5iZS50cnVlKCdkZWNvZGVkIGlucHV0cyBtdXN0IGNvbnRhaW4gbm8gRnVuZHNXaXRoZHJhd2FsIGZvciBzZWxmLXBheSBwYXRoJyk7XG5cbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZW5jb2RlIGdhcy1mcm9tLWFkZHJlc3MtYmFsYW5jZSB3aXRoIFZhbGlkRHVyaW5nIGV4cGlyYXRpb24gKHNlbGYtcGF5LCBlbXB0eSBwYXltZW50KScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFdoZW4gZ2FzRGF0YS5wYXltZW50PVtdIHRoZSBTdWkgbm9kZSByZXF1aXJlcyBhIFZhbGlkRHVyaW5nIGV4cGlyYXRpb24gdG8gcHJldmVudFxuICAgICAgLy8gcmVwbGF5IGF0dGFja3MuIEdhcyBhbmQgdHJhbnNmZXIgYXJlIGJvdGggZnVuZGVkIGZyb20gYWRkcmVzcyBiYWxhbmNlIHZpYSBHYXNDb2luLlxuICAgICAgY29uc3QgR0VORVNJU19DSEFJTl9JRCA9ICdHQUZwQ0NjUkN4VGRGZlVFTWJRYmtMQmFaeTJSTmlHQWZ2RkJoTU5wcTJrVCc7XG4gICAgICBjb25zdCBzZWxmUGF5Tm9QYXltZW50ID0geyAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsIHBheW1lbnQ6IFtdIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiB0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MsIGFtb3VudDogQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNlbGZQYXlOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShBTU9VTlQpO1xuICAgICAgdHhCdWlsZGVyLmV4cGlyYXRpb24oe1xuICAgICAgICBWYWxpZER1cmluZzoge1xuICAgICAgICAgIG1pbkVwb2NoOiB7IFNvbWU6IDUwMCB9LFxuICAgICAgICAgIG1heEVwb2NoOiB7IFNvbWU6IDUwMSB9LFxuICAgICAgICAgIG1pblRpbWVzdGFtcDogeyBOb25lOiBudWxsIH0sXG4gICAgICAgICAgbWF4VGltZXN0YW1wOiB7IE5vbmU6IG51bGwgfSxcbiAgICAgICAgICBjaGFpbjogR0VORVNJU19DSEFJTl9JRCxcbiAgICAgICAgICBub25jZTogMHhkZWFkYmVlZixcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcblxuICAgICAgLy8gU2VsZi1wYXk6IG93bmVyID09PSBzZW5kZXIsIHBheW1lbnQgZW1wdHlcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICAvLyBObyBCYWxhbmNlV2l0aGRyYXdhbCBpbnB1dCDigJQgcnVudGltZSBoYW5kbGVzIEdhc0NvaW4gZnJvbSBhZGRyZXNzIGJhbGFuY2VcbiAgICAgIGNvbnN0IGlucHV0cyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LmlucHV0cyBhcyBhbnlbXTtcbiAgICAgIGNvbnN0IGJ3SW5wdXQgPSBpbnB1dHMuZmluZChcbiAgICAgICAgKGlucCkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQubm90LmV4aXN0KGJ3SW5wdXQsICdzZWxmLXBheSBtdXN0IE5PVCBoYXZlIGEgQmFsYW5jZVdpdGhkcmF3YWwgaW5wdXQnKTtcblxuICAgICAgLy8gRmlyc3QgY29tbWFuZDogU3BsaXRDb2lucyhHYXNDb2luKSDigJQgbm8gcmVkZWVtX2Z1bmRzIGZvciBzZWxmLXBheVxuICAgICAgY29uc3QgY29tbWFuZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG4gICAgICBjb21tYW5kc1swXS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IFN1aVRyYW5zYWN0aW9uLmRlc2VyaWFsaXplU3VpVHJhbnNhY3Rpb24ocmF3VHgpO1xuICAgICAgZGVzZXJpYWxpemVkLnNlbmRlci5zaG91bGQuZXF1YWwodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgZGVzZXJpYWxpemVkLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICBjb25zdCBleHBpcmF0aW9uID0gKGRlc2VyaWFsaXplZC5leHBpcmF0aW9uIGFzIGFueSk/LlZhbGlkRHVyaW5nO1xuICAgICAgc2hvdWxkLmV4aXN0KGV4cGlyYXRpb24sICdWYWxpZER1cmluZyBleHBpcmF0aW9uIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCcpO1xuICAgICAgTnVtYmVyKGV4cGlyYXRpb24ubWluRXBvY2g/LlNvbWUgPz8gZXhwaXJhdGlvbi5taW5FcG9jaCkuc2hvdWxkLmVxdWFsKDUwMCk7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5tYXhFcG9jaD8uU29tZSA/PyBleHBpcmF0aW9uLm1heEVwb2NoKS5zaG91bGQuZXF1YWwoNTAxKTtcbiAgICAgIGV4cGlyYXRpb24uY2hhaW4uc2hvdWxkLmVxdWFsKEdFTkVTSVNfQ0hBSU5fSUQpO1xuICAgICAgTnVtYmVyKGV4cGlyYXRpb24ubm9uY2UpLnNob3VsZC5lcXVhbCgweGRlYWRiZWVmKTtcblxuICAgICAgLy8gSW5wdXRzIG11c3QgY29udGFpbiBubyBGdW5kc1dpdGhkcmF3YWwg4oCUIG9ubHkgUHVyZSBhcmdzXG4gICAgICBjb25zdCBkZWNvZGVkSW5wdXRzID0gZGVzZXJpYWxpemVkLnR4LmlucHV0cyBhcyBhbnlbXTtcbiAgICAgIGRlY29kZWRJbnB1dHNcbiAgICAgICAgLmV2ZXJ5KChpbnA6IGFueSkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCA9PT0gdW5kZWZpbmVkICYmIGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsID09PSB1bmRlZmluZWQpXG4gICAgICAgIC5zaG91bGQuYmUudHJ1ZSgnZGVjb2RlZCBpbnB1dHMgbXVzdCBjb250YWluIG5vIEZ1bmRzV2l0aGRyYXdhbCBmb3Igc2VsZi1wYXkgcGF0aCcpO1xuXG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGFuZCBjb3JyZWN0bHkgZGVjb2RlIGEgTW92ZUNhbGwgdG8gMHgyOjpjb2luOjpyZWRlZW1fZnVuZHMgd2l0aCBCYWxhbmNlV2l0aGRyYXdhbCBhcmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IGJ1aWxkU3BvbnNvcmVkVHhXaXRoQWRkcmVzc0JhbGFuY2UoKTtcbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBjb25zdCBjb21tYW5kcyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LnRyYW5zYWN0aW9ucyBhcyBhbnlbXTtcblxuICAgICAgY29tbWFuZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJyk7XG4gICAgICBjb21tYW5kc1swXS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgY29tbWFuZHNbMF0udHlwZUFyZ3VtZW50c1swXS5zaG91bGQuZXF1YWwoJzB4Mjo6c3VpOjpTVUknKTtcblxuICAgICAgLy8gVGhlIGFyZ3VtZW50IHRvIHJlZGVlbV9mdW5kcyBtdXN0IHJlZmVyZW5jZSB0aGUgQmFsYW5jZVdpdGhkcmF3YWwgaW5wdXQgKGluZGV4IDApXG4gICAgICBjb25zdCBhcmcgPSBjb21tYW5kc1swXS5hcmd1bWVudHNbMF07XG4gICAgICBhcmcua2luZC5zaG91bGQuZXF1YWwoJ0lucHV0Jyk7XG4gICAgICBhcmcuaW5kZXguc2hvdWxkLmVxdWFsKDApO1xuICAgICAgYXJnLnR5cGUuc2hvdWxkLmVxdWFsKCdvYmplY3QnKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|