@zcomb/programs-sdk 1.10.0 → 1.11.1

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.
@@ -1,757 +1 @@
1
- "use strict";
2
- /*
3
- * High-level client for the Futarchy program.
4
- * Handles account derivation, instruction building, and transaction composition.
5
- */
6
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
- if (k2 === undefined) k2 = k;
8
- var desc = Object.getOwnPropertyDescriptor(m, k);
9
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
- desc = { enumerable: true, get: function() { return m[k]; } };
11
- }
12
- Object.defineProperty(o, k2, desc);
13
- }) : (function(o, m, k, k2) {
14
- if (k2 === undefined) k2 = k;
15
- o[k2] = m[k];
16
- }));
17
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
- Object.defineProperty(o, "default", { enumerable: true, value: v });
19
- }) : function(o, v) {
20
- o["default"] = v;
21
- });
22
- var __importStar = (this && this.__importStar) || (function () {
23
- var ownKeys = function(o) {
24
- ownKeys = Object.getOwnPropertyNames || function (o) {
25
- var ar = [];
26
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
- return ar;
28
- };
29
- return ownKeys(o);
30
- };
31
- return function (mod) {
32
- if (mod && mod.__esModule) return mod;
33
- var result = {};
34
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
- __setModuleDefault(result, mod);
36
- return result;
37
- };
38
- })();
39
- Object.defineProperty(exports, "__esModule", { value: true });
40
- exports.FutarchyClient = void 0;
41
- const anchor_1 = require("@coral-xyz/anchor");
42
- const web3_js_1 = require("@solana/web3.js");
43
- const spl_token_1 = require("@solana/spl-token");
44
- const constants_1 = require("./constants");
45
- const utils_1 = require("./utils");
46
- const instructions_1 = require("./instructions");
47
- const vault_1 = require("../vault");
48
- const amm_1 = require("../amm");
49
- const idls_1 = require("../generated/idls");
50
- const multisig = __importStar(require("@sqds/multisig"));
51
- const DEFAULT_COMPUTE_UNITS = 500000;
52
- class FutarchyClient {
53
- constructor(provider, programId, computeUnits) {
54
- this.programId = programId ?? constants_1.PROGRAM_ID;
55
- this.program = new anchor_1.Program(idls_1.FutarchyIDL, provider);
56
- this.vault = new vault_1.VaultClient(provider);
57
- this.amm = new amm_1.AMMClient(provider);
58
- this.defaultComputeUnits = computeUnits ?? DEFAULT_COMPUTE_UNITS;
59
- }
60
- /* PDA Helpers */
61
- deriveDAOPDA(name) {
62
- return (0, utils_1.deriveDAOPDA)(name, this.programId);
63
- }
64
- deriveModeratorPDA(name) {
65
- return (0, utils_1.deriveModeratorPDA)(name, this.programId);
66
- }
67
- deriveProposalPDA(moderator, proposalId) {
68
- return (0, utils_1.deriveProposalPDA)(moderator, proposalId, this.programId);
69
- }
70
- /* Fetchers */
71
- async fetchDAO(daoPda) {
72
- return (0, utils_1.fetchDAOAccount)(this.program, daoPda);
73
- }
74
- async fetchModerator(moderatorPda) {
75
- return (0, utils_1.fetchModeratorAccount)(this.program, moderatorPda);
76
- }
77
- async fetchProposal(proposalPda) {
78
- return (0, utils_1.fetchProposalAccount)(this.program, proposalPda);
79
- }
80
- /* Proposal Helpers */
81
- isProposalExpired(proposal) {
82
- return (0, utils_1.isProposalExpired)(proposal);
83
- }
84
- getTimeRemaining(proposal) {
85
- return (0, utils_1.getTimeRemaining)(proposal);
86
- }
87
- getComputeUnits(options) {
88
- return options?.computeUnits ?? this.defaultComputeUnits;
89
- }
90
- maybeAddComputeBudget(options) {
91
- if (options?.includeCuBudget === false) {
92
- return [];
93
- }
94
- return [web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: this.getComputeUnits(options) })];
95
- }
96
- /* Instruction Builders */
97
- async initializeModerator(admin, baseMint, quoteMint, name, options) {
98
- const [moderatorPda] = this.deriveModeratorPDA(name);
99
- const builder = (0, instructions_1.initializeModerator)(this.program, admin, baseMint, quoteMint, moderatorPda, name).preInstructions(this.maybeAddComputeBudget(options));
100
- return { builder, moderatorPda, name };
101
- }
102
- async addHistoricalProposal(admin, moderatorPda, numOptions, winningIdx, length, createdAt, metadata, options) {
103
- const moderator = await this.fetchModerator(moderatorPda);
104
- const proposalId = moderator.proposalIdCounter;
105
- const [proposalPda] = this.deriveProposalPDA(moderatorPda, proposalId);
106
- const builder = (0, instructions_1.addHistoricalProposal)(this.program, admin, moderatorPda, proposalPda, numOptions, winningIdx, length, createdAt, metadata).preInstructions(this.maybeAddComputeBudget(options));
107
- return { builder, proposalPda, proposalId };
108
- }
109
- async initializeProposal(creator, moderatorPda, proposalParams, metadata, options) {
110
- const moderator = await this.fetchModerator(moderatorPda);
111
- const proposalId = moderator.proposalIdCounter;
112
- const [proposalPda] = this.deriveProposalPDA(moderatorPda, proposalId);
113
- // Derive vault PDA (proposal is the owner, nonce=proposalId)
114
- const [vaultPda] = (0, vault_1.deriveVaultPDA)(proposalPda, proposalId, this.vault.programId);
115
- // Derive conditional mints for initial 2 options
116
- const [condBaseMint0] = (0, vault_1.deriveConditionalMint)(vaultPda, vault_1.VaultType.Base, 0, this.vault.programId);
117
- const [condBaseMint1] = (0, vault_1.deriveConditionalMint)(vaultPda, vault_1.VaultType.Base, 1, this.vault.programId);
118
- const [condQuoteMint0] = (0, vault_1.deriveConditionalMint)(vaultPda, vault_1.VaultType.Quote, 0, this.vault.programId);
119
- const [condQuoteMint1] = (0, vault_1.deriveConditionalMint)(vaultPda, vault_1.VaultType.Quote, 1, this.vault.programId);
120
- // Derive pool PDAs for initial 2 options (proposal is admin, mintA=condQuote, mintB=condBase)
121
- const [pool0] = (0, amm_1.derivePoolPDA)(proposalPda, condQuoteMint0, condBaseMint0, this.amm.programId);
122
- const [pool1] = (0, amm_1.derivePoolPDA)(proposalPda, condQuoteMint1, condBaseMint1, this.amm.programId);
123
- // Derive reserves and fee vaults
124
- const [reserveA0] = (0, amm_1.deriveReservePDA)(pool0, condQuoteMint0, this.amm.programId);
125
- const [reserveB0] = (0, amm_1.deriveReservePDA)(pool0, condBaseMint0, this.amm.programId);
126
- const [feeVault0] = (0, amm_1.deriveFeeVaultPDA)(pool0, this.amm.programId);
127
- const [reserveA1] = (0, amm_1.deriveReservePDA)(pool1, condQuoteMint1, this.amm.programId);
128
- const [reserveB1] = (0, amm_1.deriveReservePDA)(pool1, condBaseMint1, this.amm.programId);
129
- const [feeVault1] = (0, amm_1.deriveFeeVaultPDA)(pool1, this.amm.programId);
130
- // Vault token accounts
131
- const baseTokenAcc = (0, spl_token_1.getAssociatedTokenAddressSync)(moderator.baseMint, vaultPda, true);
132
- const quoteTokenAcc = (0, spl_token_1.getAssociatedTokenAddressSync)(moderator.quoteMint, vaultPda, true);
133
- // Build remaining accounts in expected order (see initialize_proposal.rs)
134
- const remainingAccounts = [
135
- { pubkey: moderator.baseMint, isSigner: false, isWritable: false }, // 0: base_mint
136
- { pubkey: moderator.quoteMint, isSigner: false, isWritable: false }, // 1: quote_mint
137
- { pubkey: vaultPda, isSigner: false, isWritable: true }, // 2: vault
138
- { pubkey: baseTokenAcc, isSigner: false, isWritable: true }, // 3: base_token_acc
139
- { pubkey: quoteTokenAcc, isSigner: false, isWritable: true }, // 4: quote_token_acc
140
- { pubkey: condBaseMint0, isSigner: false, isWritable: true }, // 5: cond_base_mint_0
141
- { pubkey: condBaseMint1, isSigner: false, isWritable: true }, // 6: cond_base_mint_1
142
- { pubkey: condQuoteMint0, isSigner: false, isWritable: true }, // 7: cond_quote_mint_0
143
- { pubkey: condQuoteMint1, isSigner: false, isWritable: true }, // 8: cond_quote_mint_1
144
- { pubkey: pool0, isSigner: false, isWritable: true }, // 9: pool_0
145
- { pubkey: reserveA0, isSigner: false, isWritable: true }, // 10: reserve_a_0
146
- { pubkey: reserveB0, isSigner: false, isWritable: true }, // 11: reserve_b_0
147
- { pubkey: amm_1.FEE_AUTHORITY, isSigner: false, isWritable: false }, // 12: fee_authority
148
- { pubkey: feeVault0, isSigner: false, isWritable: true }, // 13: fee_vault_0
149
- { pubkey: pool1, isSigner: false, isWritable: true }, // 14: pool_1
150
- { pubkey: reserveA1, isSigner: false, isWritable: true }, // 15: reserve_a_1
151
- { pubkey: reserveB1, isSigner: false, isWritable: true }, // 16: reserve_b_1
152
- { pubkey: feeVault1, isSigner: false, isWritable: true }, // 17: fee_vault_1
153
- ];
154
- const builder = (0, instructions_1.initializeProposal)(this.program, creator, moderatorPda, proposalPda, proposalParams, metadata ?? null, remainingAccounts).preInstructions(this.maybeAddComputeBudget(options));
155
- return {
156
- builder,
157
- proposalPda,
158
- proposalId,
159
- vaultPda,
160
- pools: [pool0, pool1],
161
- condBaseMints: [condBaseMint0, condBaseMint1],
162
- condQuoteMints: [condQuoteMint0, condQuoteMint1],
163
- };
164
- }
165
- async addOption(creator, proposalPda, options) {
166
- const proposal = await this.fetchProposal(proposalPda);
167
- const optionIndex = proposal.numOptions;
168
- // Derive new conditional mints
169
- const [condBaseMint] = (0, vault_1.deriveConditionalMint)(proposal.vault, vault_1.VaultType.Base, optionIndex, this.vault.programId);
170
- const [condQuoteMint] = (0, vault_1.deriveConditionalMint)(proposal.vault, vault_1.VaultType.Quote, optionIndex, this.vault.programId);
171
- // Derive pool PDA
172
- const [pool] = (0, amm_1.derivePoolPDA)(proposalPda, condQuoteMint, condBaseMint, this.amm.programId);
173
- const [reserveA] = (0, amm_1.deriveReservePDA)(pool, condQuoteMint, this.amm.programId);
174
- const [reserveB] = (0, amm_1.deriveReservePDA)(pool, condBaseMint, this.amm.programId);
175
- const [feeVault] = (0, amm_1.deriveFeeVaultPDA)(pool, this.amm.programId);
176
- // Build remaining accounts (see add_option.rs)
177
- const remainingAccounts = [
178
- { pubkey: proposal.vault, isSigner: false, isWritable: true }, // 0: vault
179
- { pubkey: condBaseMint, isSigner: false, isWritable: true }, // 1: cond_base_mint
180
- { pubkey: condQuoteMint, isSigner: false, isWritable: true }, // 2: cond_quote_mint
181
- { pubkey: pool, isSigner: false, isWritable: true }, // 3: pool
182
- { pubkey: reserveA, isSigner: false, isWritable: true }, // 4: reserve_a
183
- { pubkey: reserveB, isSigner: false, isWritable: true }, // 5: reserve_b
184
- { pubkey: amm_1.FEE_AUTHORITY, isSigner: false, isWritable: false }, // 6: fee_authority
185
- { pubkey: feeVault, isSigner: false, isWritable: true }, // 7: fee_vault
186
- ];
187
- const builder = (0, instructions_1.addOption)(this.program, creator, proposalPda, remainingAccounts)
188
- .preInstructions(this.maybeAddComputeBudget(options));
189
- return { builder, optionIndex, pool, condBaseMint, condQuoteMint };
190
- }
191
- async launchProposal(creator, proposalPda, baseAmount, quoteAmount, options) {
192
- const proposal = await this.fetchProposal(proposalPda);
193
- const vault = await this.vault.fetchVault(proposal.vault);
194
- const numOptions = proposal.numOptions;
195
- // Slice arrays to numOptions (fixed-size arrays from Rust include empty slots)
196
- const condBaseMints = vault.condBaseMints.slice(0, numOptions);
197
- const condQuoteMints = vault.condQuoteMints.slice(0, numOptions);
198
- // Pre-create conditional ATAs for 3+ options to avoid exceeding the
199
- // 64 instruction trace limit. Each ATA creation via vault deposit adds
200
- // 5 inner instructions; with 4 options that's 40 extra instructions.
201
- const shouldEnsureATAs = options?.ensureATAs ?? (numOptions >= 3);
202
- if (shouldEnsureATAs) {
203
- await this._createConditionalATAs(creator, condBaseMints, condQuoteMints);
204
- }
205
- const pools = proposal.pools.slice(0, numOptions);
206
- // Derive all user conditional token ATAs
207
- const userCondBaseATAs = condBaseMints.map((m) => (0, spl_token_1.getAssociatedTokenAddressSync)(m, creator));
208
- const userCondQuoteATAs = condQuoteMints.map((m) => (0, spl_token_1.getAssociatedTokenAddressSync)(m, creator));
209
- // Derive reserve accounts for each pool
210
- const reservesA = [];
211
- const reservesB = [];
212
- for (let i = 0; i < numOptions; i++) {
213
- const [resA] = (0, amm_1.deriveReservePDA)(pools[i], condQuoteMints[i], this.amm.programId);
214
- const [resB] = (0, amm_1.deriveReservePDA)(pools[i], condBaseMints[i], this.amm.programId);
215
- reservesA.push(resA);
216
- reservesB.push(resB);
217
- }
218
- // Build remaining accounts (see launch_proposal.rs)
219
- // Layout: 6 fixed + 7*N variable
220
- const remainingAccounts = [
221
- { pubkey: vault.baseMint.address, isSigner: false, isWritable: false }, // 0: base_mint
222
- { pubkey: vault.quoteMint.address, isSigner: false, isWritable: false }, // 1: quote_mint
223
- { pubkey: (0, spl_token_1.getAssociatedTokenAddressSync)(vault.baseMint.address, proposal.vault, true), isSigner: false, isWritable: true }, // 2: vault_base_ata
224
- { pubkey: (0, spl_token_1.getAssociatedTokenAddressSync)(vault.quoteMint.address, proposal.vault, true), isSigner: false, isWritable: true }, // 3: vault_quote_ata
225
- { pubkey: (0, spl_token_1.getAssociatedTokenAddressSync)(vault.baseMint.address, creator), isSigner: false, isWritable: true }, // 4: user_base_ata
226
- { pubkey: (0, spl_token_1.getAssociatedTokenAddressSync)(vault.quoteMint.address, creator), isSigner: false, isWritable: true }, // 5: user_quote_ata
227
- ];
228
- // 6..6+N: cond_base_mints
229
- for (const mint of condBaseMints) {
230
- remainingAccounts.push({ pubkey: mint, isSigner: false, isWritable: true });
231
- }
232
- // 6+N..6+2N: cond_quote_mints
233
- for (const mint of condQuoteMints) {
234
- remainingAccounts.push({ pubkey: mint, isSigner: false, isWritable: true });
235
- }
236
- // 6+2N..6+3N: user_cond_base_atas
237
- for (const ata of userCondBaseATAs) {
238
- remainingAccounts.push({ pubkey: ata, isSigner: false, isWritable: true });
239
- }
240
- // 6+3N..6+4N: user_cond_quote_atas
241
- for (const ata of userCondQuoteATAs) {
242
- remainingAccounts.push({ pubkey: ata, isSigner: false, isWritable: true });
243
- }
244
- // 6+4N..6+5N: pools
245
- for (const pool of pools) {
246
- remainingAccounts.push({ pubkey: pool, isSigner: false, isWritable: true });
247
- }
248
- // 6+5N..6+6N: reserves_a
249
- for (const res of reservesA) {
250
- remainingAccounts.push({ pubkey: res, isSigner: false, isWritable: true });
251
- }
252
- // 6+6N..6+7N: reserves_b
253
- for (const res of reservesB) {
254
- remainingAccounts.push({ pubkey: res, isSigner: false, isWritable: true });
255
- }
256
- const builder = (0, instructions_1.launchProposal)(this.program, creator, proposalPda, proposal.vault, baseAmount, quoteAmount, remainingAccounts).preInstructions(this.maybeAddComputeBudget(options));
257
- return { builder };
258
- }
259
- /**
260
- * Pre-creates all conditional token ATAs for a user before launching a proposal.
261
- *
262
- * This is REQUIRED for proposals with 3+ options to avoid exceeding Solana's
263
- * max instruction trace length limit (64 instructions). The vault's deposit CPI
264
- * creates ATAs on-the-fly, each requiring 5 inner instructions. For 4 options:
265
- * 8 ATAs × 5 = 40 extra instructions, pushing the total over 64.
266
- *
267
- * Pre-creating ATAs eliminates this overhead, reducing the trace to ~32 instructions.
268
- *
269
- * @param creator - The user who will receive conditional tokens
270
- * @param proposalPda - The proposal PDA (must be initialized but not launched)
271
- * @returns Transaction signature
272
- */
273
- async ensureConditionalATAs(creator, proposalPda) {
274
- const proposal = await this.fetchProposal(proposalPda);
275
- const vault = await this.vault.fetchVault(proposal.vault);
276
- const condBaseMints = vault.condBaseMints.slice(0, proposal.numOptions);
277
- const condQuoteMints = vault.condQuoteMints.slice(0, proposal.numOptions);
278
- return this._createConditionalATAs(creator, condBaseMints, condQuoteMints);
279
- }
280
- /**
281
- * Internal helper to create conditional ATAs given mint arrays.
282
- * Used by both ensureConditionalATAs and launchProposal to avoid redundant fetches.
283
- */
284
- async _createConditionalATAs(creator, condBaseMints, condQuoteMints) {
285
- const provider = this.program.provider;
286
- // Build ATA creation instructions (idempotent - won't fail if exists)
287
- const instructions = [];
288
- for (let i = 0; i < condBaseMints.length; i++) {
289
- const userCondBaseAta = (0, spl_token_1.getAssociatedTokenAddressSync)(condBaseMints[i], creator);
290
- const userCondQuoteAta = (0, spl_token_1.getAssociatedTokenAddressSync)(condQuoteMints[i], creator);
291
- instructions.push((0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(creator, userCondBaseAta, creator, condBaseMints[i]), (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(creator, userCondQuoteAta, creator, condQuoteMints[i]));
292
- }
293
- // Send transaction
294
- const tx = new web3_js_1.Transaction().add(...instructions);
295
- return provider.sendAndConfirm(tx);
296
- }
297
- async finalizeProposal(signer, proposalPda, options) {
298
- const proposal = await this.fetchProposal(proposalPda);
299
- const vault = await this.vault.fetchVault(proposal.vault);
300
- const numOptions = proposal.numOptions;
301
- // Build remaining accounts (3 per pool: pool, reserve_a, reserve_b)
302
- const remainingAccounts = [];
303
- for (let i = 0; i < numOptions; i++) {
304
- const pool = proposal.pools[i];
305
- const [reserveA] = (0, amm_1.deriveReservePDA)(pool, vault.condQuoteMints[i], this.amm.programId);
306
- const [reserveB] = (0, amm_1.deriveReservePDA)(pool, vault.condBaseMints[i], this.amm.programId);
307
- remainingAccounts.push({ pubkey: pool, isSigner: false, isWritable: true });
308
- remainingAccounts.push({ pubkey: reserveA, isSigner: false, isWritable: false });
309
- remainingAccounts.push({ pubkey: reserveB, isSigner: false, isWritable: false });
310
- }
311
- const builder = (0, instructions_1.finalizeProposal)(this.program, signer, proposalPda, proposal.vault, remainingAccounts).preInstructions(this.maybeAddComputeBudget(options));
312
- return { builder };
313
- }
314
- async redeemLiquidity(creator, proposalPda, options) {
315
- const proposal = await this.fetchProposal(proposalPda);
316
- const vault = await this.vault.fetchVault(proposal.vault);
317
- const numOptions = proposal.numOptions;
318
- const { winningIdx } = (0, utils_1.parseProposalState)(proposal.state);
319
- if (winningIdx === null) {
320
- throw new Error("Proposal not finalized");
321
- }
322
- const winningPool = proposal.pools[winningIdx];
323
- // Derive winning pool reserves
324
- const [reserveA] = (0, amm_1.deriveReservePDA)(winningPool, vault.condQuoteMints[winningIdx], this.amm.programId);
325
- const [reserveB] = (0, amm_1.deriveReservePDA)(winningPool, vault.condBaseMints[winningIdx], this.amm.programId);
326
- // User's winning conditional token ATAs
327
- const creatorCondQuoteAta = (0, spl_token_1.getAssociatedTokenAddressSync)(vault.condQuoteMints[winningIdx], creator);
328
- const creatorCondBaseAta = (0, spl_token_1.getAssociatedTokenAddressSync)(vault.condBaseMints[winningIdx], creator);
329
- // Build remaining accounts (see redeem_liquidity.rs)
330
- const remainingAccounts = [
331
- // remove_liquidity accounts (0-3)
332
- { pubkey: reserveA, isSigner: false, isWritable: true },
333
- { pubkey: reserveB, isSigner: false, isWritable: true },
334
- { pubkey: creatorCondQuoteAta, isSigner: false, isWritable: true },
335
- { pubkey: creatorCondBaseAta, isSigner: false, isWritable: true },
336
- // redeem_winnings base fixed accounts (4-6)
337
- { pubkey: vault.baseMint.address, isSigner: false, isWritable: false },
338
- { pubkey: (0, spl_token_1.getAssociatedTokenAddressSync)(vault.baseMint.address, proposal.vault, true), isSigner: false, isWritable: true },
339
- { pubkey: (0, spl_token_1.getAssociatedTokenAddressSync)(vault.baseMint.address, creator), isSigner: false, isWritable: true },
340
- ];
341
- // redeem_winnings base remaining (7..7+2N): [cond_base_mint_i, user_cond_base_ata_i]
342
- for (let i = 0; i < numOptions; i++) {
343
- remainingAccounts.push({ pubkey: vault.condBaseMints[i], isSigner: false, isWritable: true });
344
- remainingAccounts.push({ pubkey: (0, spl_token_1.getAssociatedTokenAddressSync)(vault.condBaseMints[i], creator), isSigner: false, isWritable: true });
345
- }
346
- // redeem_winnings quote fixed accounts
347
- remainingAccounts.push({ pubkey: vault.quoteMint.address, isSigner: false, isWritable: false });
348
- remainingAccounts.push({ pubkey: (0, spl_token_1.getAssociatedTokenAddressSync)(vault.quoteMint.address, proposal.vault, true), isSigner: false, isWritable: true });
349
- remainingAccounts.push({ pubkey: (0, spl_token_1.getAssociatedTokenAddressSync)(vault.quoteMint.address, creator), isSigner: false, isWritable: true });
350
- // redeem_winnings quote remaining: [cond_quote_mint_i, user_cond_quote_ata_i]
351
- for (let i = 0; i < numOptions; i++) {
352
- remainingAccounts.push({ pubkey: vault.condQuoteMints[i], isSigner: false, isWritable: true });
353
- remainingAccounts.push({ pubkey: (0, spl_token_1.getAssociatedTokenAddressSync)(vault.condQuoteMints[i], creator), isSigner: false, isWritable: true });
354
- }
355
- const builder = (0, instructions_1.redeemLiquidity)(this.program, creator, proposalPda, proposal.vault, winningPool, remainingAccounts).preInstructions(this.maybeAddComputeBudget(options));
356
- return { builder, numOptions };
357
- }
358
- /**
359
- * Creates an Address Lookup Table for redemption operations.
360
- * Required for proposals with 3+ options to avoid exceeding transaction size limits.
361
- *
362
- * @param creator - The user redeeming (creator of proposal or liquidity provider)
363
- * @param proposalPda - The proposal PDA
364
- * @returns ALT address
365
- */
366
- async createRedemptionALT(creator, proposalPda) {
367
- const provider = this.program.provider;
368
- const proposal = await this.fetchProposal(proposalPda);
369
- const vault = await this.vault.fetchVault(proposal.vault);
370
- const numOptions = proposal.numOptions;
371
- const { winningIdx } = (0, utils_1.parseProposalState)(proposal.state);
372
- if (winningIdx === null) {
373
- throw new Error("Proposal not finalized");
374
- }
375
- const addresses = [
376
- // Programs
377
- this.programId,
378
- this.vault.programId,
379
- this.amm.programId,
380
- web3_js_1.SystemProgram.programId,
381
- spl_token_1.TOKEN_PROGRAM_ID,
382
- spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
383
- // Core accounts
384
- proposalPda,
385
- proposal.vault,
386
- proposal.moderator,
387
- vault.baseMint.address,
388
- vault.quoteMint.address,
389
- // Winning pool and reserves
390
- proposal.pools[winningIdx],
391
- // Vault token accounts
392
- (0, spl_token_1.getAssociatedTokenAddressSync)(vault.baseMint.address, proposal.vault, true),
393
- (0, spl_token_1.getAssociatedTokenAddressSync)(vault.quoteMint.address, proposal.vault, true),
394
- // Creator's base/quote ATAs
395
- (0, spl_token_1.getAssociatedTokenAddressSync)(vault.baseMint.address, creator),
396
- (0, spl_token_1.getAssociatedTokenAddressSync)(vault.quoteMint.address, creator),
397
- ];
398
- // Winning pool reserves
399
- const [reserveA] = (0, amm_1.deriveReservePDA)(proposal.pools[winningIdx], vault.condQuoteMints[winningIdx], this.amm.programId);
400
- const [reserveB] = (0, amm_1.deriveReservePDA)(proposal.pools[winningIdx], vault.condBaseMints[winningIdx], this.amm.programId);
401
- addresses.push(reserveA, reserveB);
402
- // Per-option accounts (conditional mints and user ATAs)
403
- for (let i = 0; i < numOptions; i++) {
404
- addresses.push(vault.condBaseMints[i], vault.condQuoteMints[i], (0, spl_token_1.getAssociatedTokenAddressSync)(vault.condBaseMints[i], creator), (0, spl_token_1.getAssociatedTokenAddressSync)(vault.condQuoteMints[i], creator));
405
- }
406
- // Get recent slot for ALT creation
407
- const slot = await provider.connection.getSlot("finalized");
408
- const [createIx, altAddress] = web3_js_1.AddressLookupTableProgram.createLookupTable({
409
- authority: creator,
410
- payer: creator,
411
- recentSlot: slot,
412
- });
413
- // Create ALT
414
- const createTx = new web3_js_1.Transaction().add(createIx);
415
- const { blockhash: createBlockhash, lastValidBlockHeight: createLastValidBlockHeight } = await provider.connection.getLatestBlockhash('confirmed');
416
- createTx.recentBlockhash = createBlockhash;
417
- createTx.feePayer = creator;
418
- const signedTx = await provider.wallet.signTransaction(createTx);
419
- const sig = await provider.connection.sendRawTransaction(signedTx.serialize(), {
420
- skipPreflight: true,
421
- });
422
- await provider.connection.confirmTransaction({
423
- signature: sig,
424
- blockhash: createBlockhash,
425
- lastValidBlockHeight: createLastValidBlockHeight,
426
- }, "confirmed");
427
- // Extend ALT with addresses
428
- // Use skipPreflight to avoid race condition where simulation sees stale state
429
- // before previous extend has propagated (same pattern as CREATE above)
430
- const CHUNK_SIZE = 20;
431
- for (let i = 0; i < addresses.length; i += CHUNK_SIZE) {
432
- const chunk = addresses.slice(i, i + CHUNK_SIZE);
433
- const extendIx = web3_js_1.AddressLookupTableProgram.extendLookupTable({
434
- payer: creator,
435
- authority: creator,
436
- lookupTable: altAddress,
437
- addresses: chunk,
438
- });
439
- const extendTx = new web3_js_1.Transaction().add(extendIx);
440
- const { blockhash: extendBlockhash, lastValidBlockHeight: extendLastValidBlockHeight } = await provider.connection.getLatestBlockhash('confirmed');
441
- extendTx.recentBlockhash = extendBlockhash;
442
- extendTx.feePayer = creator;
443
- const signedExtendTx = await provider.wallet.signTransaction(extendTx);
444
- const extendSig = await provider.connection.sendRawTransaction(signedExtendTx.serialize(), {
445
- skipPreflight: true,
446
- });
447
- await provider.connection.confirmTransaction({
448
- signature: extendSig,
449
- blockhash: extendBlockhash,
450
- lastValidBlockHeight: extendLastValidBlockHeight,
451
- }, "confirmed");
452
- }
453
- return { altAddress };
454
- }
455
- /**
456
- * Builds a versioned transaction for redeeming liquidity with ALT.
457
- * Required for proposals with 3+ options to avoid exceeding transaction size limits.
458
- *
459
- * @param creator - The user redeeming
460
- * @param proposalPda - The proposal PDA
461
- * @param altAddress - Optional ALT address (will be created if not provided for 3+ options)
462
- * @returns Unsigned versioned transaction, ALT address, number of options, and blockhash info for confirmation
463
- */
464
- async redeemLiquidityVersioned(creator, proposalPda, altAddress) {
465
- const provider = this.program.provider;
466
- const { builder, numOptions } = await this.redeemLiquidity(creator, proposalPda);
467
- // Create ALT if not provided and needed
468
- let altPubkey = altAddress;
469
- let verifiedALT = null;
470
- if (!altPubkey && numOptions >= 3) {
471
- console.log(` Creating redemption ALT for ${numOptions} options...`);
472
- const result = await this.createRedemptionALT(creator, proposalPda);
473
- altPubkey = result.altAddress;
474
- console.log(` ✓ Redemption ALT created: ${altPubkey.toBase58()}`);
475
- // Wait for ALT to be fully available with all addresses
476
- // Use longer delays after extending to ensure propagation
477
- console.log(` Waiting for ALT propagation...`);
478
- const expectedAddresses = 18 + (numOptions * 4); // Base accounts + per-option accounts
479
- let attempts = 0;
480
- // Initial delay after extension
481
- await new Promise(resolve => setTimeout(resolve, 2000));
482
- while (attempts < 30) {
483
- const altAccount = await provider.connection.getAddressLookupTable(altPubkey, {
484
- commitment: 'confirmed',
485
- });
486
- if (altAccount.value) {
487
- const addressCount = altAccount.value.state.addresses.length;
488
- console.log(` Attempt ${attempts + 1}: ALT has ${addressCount}/${expectedAddresses} addresses`);
489
- if (addressCount >= expectedAddresses) {
490
- verifiedALT = altAccount.value;
491
- console.log(` ✓ ALT verified with ${addressCount} addresses`);
492
- break;
493
- }
494
- }
495
- await new Promise(resolve => setTimeout(resolve, 1000));
496
- attempts++;
497
- }
498
- if (!verifiedALT) {
499
- throw new Error(`ALT failed to populate with expected ${expectedAddresses} addresses after ${attempts} attempts`);
500
- }
501
- }
502
- if (!altPubkey) {
503
- throw new Error("ALT address required for multi-option redemption");
504
- }
505
- // Fetch ALT if we don't have it verified already
506
- if (!verifiedALT) {
507
- verifiedALT = await this.fetchALT(altPubkey);
508
- }
509
- // Build instruction
510
- const instruction = await builder.instruction();
511
- const computeBudgetIx = web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: 500000 });
512
- // Get fresh blockhash with lastValidBlockHeight for confirmation tracking
513
- const { blockhash, lastValidBlockHeight } = await provider.connection.getLatestBlockhash('confirmed');
514
- // Build versioned transaction using the verified ALT (no re-fetch)
515
- const versionedTx = this.buildVersionedTxWithALT(creator, [computeBudgetIx, instruction], verifiedALT, blockhash);
516
- // Return the versioned transaction along with blockhash info for proper confirmation
517
- // This allows the caller to use their own signing mechanism (e.g., keypair.sign)
518
- return { versionedTx, altAddress: altPubkey, numOptions, blockhash, lastValidBlockHeight };
519
- }
520
- /**
521
- * Helper to send a signed versioned transaction with robust confirmation handling.
522
- * Uses blockhash-based confirmation to properly detect transaction expiration
523
- * instead of relying on a fixed timeout.
524
- *
525
- * @param signedTx - The signed versioned transaction to send
526
- * @param confirmationInfo - Optional blockhash info from when the transaction was built.
527
- * If not provided, a fresh blockhash will be fetched (less accurate).
528
- */
529
- async sendVersionedTransaction(signedTx, confirmationInfo) {
530
- const provider = this.program.provider;
531
- // Use provided blockhash info or fetch fresh one
532
- // Using the original blockhash is more accurate for detecting expiration
533
- let blockhash;
534
- let lastValidBlockHeight;
535
- if (confirmationInfo) {
536
- blockhash = confirmationInfo.blockhash;
537
- lastValidBlockHeight = confirmationInfo.lastValidBlockHeight;
538
- }
539
- else {
540
- // Fallback: get fresh blockhash (may wait longer than necessary if tx already expired)
541
- const latestBlockhash = await provider.connection.getLatestBlockhash('confirmed');
542
- blockhash = latestBlockhash.blockhash;
543
- lastValidBlockHeight = latestBlockhash.lastValidBlockHeight;
544
- }
545
- const signature = await provider.connection.sendTransaction(signedTx, {
546
- skipPreflight: false,
547
- preflightCommitment: 'confirmed',
548
- });
549
- // Use blockhash-based confirmation which waits until either:
550
- // 1. Transaction is confirmed
551
- // 2. Blockhash expires (lastValidBlockHeight passed)
552
- // This is more robust than a fixed timeout on congested networks
553
- await provider.connection.confirmTransaction({
554
- signature,
555
- blockhash,
556
- lastValidBlockHeight,
557
- }, 'confirmed');
558
- return signature;
559
- }
560
- /* Address Lookup Table */
561
- async createProposalALT(creator, moderatorPda, numOptions = 2) {
562
- const provider = this.program.provider;
563
- const moderator = await this.fetchModerator(moderatorPda);
564
- const proposalId = moderator.proposalIdCounter;
565
- const [proposalPda] = this.deriveProposalPDA(moderatorPda, proposalId);
566
- const [vaultPda] = (0, vault_1.deriveVaultPDA)(proposalPda, proposalId, this.vault.programId);
567
- const addresses = [
568
- // Programs
569
- this.programId,
570
- this.vault.programId,
571
- this.amm.programId,
572
- web3_js_1.SystemProgram.programId,
573
- spl_token_1.TOKEN_PROGRAM_ID,
574
- spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
575
- // Core accounts
576
- moderatorPda,
577
- proposalPda,
578
- vaultPda,
579
- moderator.baseMint,
580
- moderator.quoteMint,
581
- amm_1.FEE_AUTHORITY,
582
- // Vault token accounts
583
- (0, spl_token_1.getAssociatedTokenAddressSync)(moderator.baseMint, vaultPda, true),
584
- (0, spl_token_1.getAssociatedTokenAddressSync)(moderator.quoteMint, vaultPda, true),
585
- // Creator's base/quote ATAs
586
- (0, spl_token_1.getAssociatedTokenAddressSync)(moderator.baseMint, creator),
587
- (0, spl_token_1.getAssociatedTokenAddressSync)(moderator.quoteMint, creator),
588
- ];
589
- // Per-option accounts
590
- for (let i = 0; i < numOptions; i++) {
591
- const [condBaseMint] = (0, vault_1.deriveConditionalMint)(vaultPda, vault_1.VaultType.Base, i, this.vault.programId);
592
- const [condQuoteMint] = (0, vault_1.deriveConditionalMint)(vaultPda, vault_1.VaultType.Quote, i, this.vault.programId);
593
- const [pool] = (0, amm_1.derivePoolPDA)(proposalPda, condQuoteMint, condBaseMint, this.amm.programId);
594
- const [reserveA] = (0, amm_1.deriveReservePDA)(pool, condQuoteMint, this.amm.programId);
595
- const [reserveB] = (0, amm_1.deriveReservePDA)(pool, condBaseMint, this.amm.programId);
596
- const [feeVault] = (0, amm_1.deriveFeeVaultPDA)(pool, this.amm.programId);
597
- addresses.push(condBaseMint, condQuoteMint, pool, reserveA, reserveB, feeVault,
598
- // Creator's conditional token ATAs
599
- (0, spl_token_1.getAssociatedTokenAddressSync)(condBaseMint, creator), (0, spl_token_1.getAssociatedTokenAddressSync)(condQuoteMint, creator));
600
- }
601
- // Get the most recent slot using "finalized" commitment for stability
602
- const slot = await provider.connection.getSlot("finalized");
603
- const [createIx, altAddress] = web3_js_1.AddressLookupTableProgram.createLookupTable({
604
- authority: creator,
605
- payer: creator,
606
- recentSlot: slot,
607
- });
608
- // Send create transaction immediately, skip preflight to avoid slot timing issues
609
- const createTx = new web3_js_1.Transaction().add(createIx);
610
- const { blockhash: createBlockhash, lastValidBlockHeight: createLastValidBlockHeight } = await provider.connection.getLatestBlockhash('confirmed');
611
- createTx.recentBlockhash = createBlockhash;
612
- createTx.feePayer = creator;
613
- const signedTx = await provider.wallet.signTransaction(createTx);
614
- const sig = await provider.connection.sendRawTransaction(signedTx.serialize(), {
615
- skipPreflight: true,
616
- });
617
- await provider.connection.confirmTransaction({
618
- signature: sig,
619
- blockhash: createBlockhash,
620
- lastValidBlockHeight: createLastValidBlockHeight,
621
- }, "confirmed");
622
- // Split addresses into chunks to avoid transaction size limits
623
- // Each address is 32 bytes, ~20 addresses per extend instruction is safe
624
- // Use skipPreflight to avoid race condition where simulation sees stale state
625
- // before previous extend has propagated (same pattern as CREATE above)
626
- const CHUNK_SIZE = 20;
627
- for (let i = 0; i < addresses.length; i += CHUNK_SIZE) {
628
- const chunk = addresses.slice(i, i + CHUNK_SIZE);
629
- const extendIx = web3_js_1.AddressLookupTableProgram.extendLookupTable({
630
- payer: creator,
631
- authority: creator,
632
- lookupTable: altAddress,
633
- addresses: chunk,
634
- });
635
- const extendTx = new web3_js_1.Transaction().add(extendIx);
636
- const { blockhash: extendBlockhash, lastValidBlockHeight: extendLastValidBlockHeight } = await provider.connection.getLatestBlockhash('confirmed');
637
- extendTx.recentBlockhash = extendBlockhash;
638
- extendTx.feePayer = creator;
639
- const signedExtendTx = await provider.wallet.signTransaction(extendTx);
640
- const extendSig = await provider.connection.sendRawTransaction(signedExtendTx.serialize(), {
641
- skipPreflight: true,
642
- });
643
- await provider.connection.confirmTransaction({
644
- signature: extendSig,
645
- blockhash: extendBlockhash,
646
- lastValidBlockHeight: extendLastValidBlockHeight,
647
- }, "confirmed");
648
- }
649
- return { altAddress };
650
- }
651
- async fetchALT(altAddress) {
652
- const alt = await this.program.provider.connection.getAddressLookupTable(altAddress);
653
- if (!alt.value) {
654
- throw new Error("ALT not found");
655
- }
656
- return alt.value;
657
- }
658
- async buildVersionedTx(payer, instructions, altAddress) {
659
- const provider = this.program.provider;
660
- const alt = await this.fetchALT(altAddress);
661
- const { blockhash, lastValidBlockHeight } = await provider.connection.getLatestBlockhash('confirmed');
662
- const versionedTx = this.buildVersionedTxWithALT(payer, instructions, alt, blockhash);
663
- return { versionedTx, blockhash, lastValidBlockHeight };
664
- }
665
- buildVersionedTxWithALT(payer, instructions, alt, blockhash) {
666
- const message = new web3_js_1.TransactionMessage({
667
- payerKey: payer,
668
- recentBlockhash: blockhash,
669
- instructions,
670
- }).compileToV0Message([alt]);
671
- return new web3_js_1.VersionedTransaction(message);
672
- }
673
- /* DAO Methods */
674
- deriveMintCreateKeyPDA(daoPda, name) {
675
- return (0, utils_1.deriveMintCreateKeyPDA)(daoPda, name, this.programId);
676
- }
677
- async fetchSquadsProgramConfig() {
678
- const [programConfigPda] = multisig.getProgramConfigPda({
679
- programId: constants_1.SQUADS_PROGRAM_ID,
680
- });
681
- const programConfig = await multisig.accounts.ProgramConfig.fromAccountAddress(this.program.provider.connection, programConfigPda);
682
- return {
683
- programConfig: programConfigPda,
684
- programConfigTreasury: programConfig.treasury,
685
- };
686
- }
687
- deriveMultisigPda(createKey) {
688
- const [multisigPda] = multisig.getMultisigPda({
689
- createKey,
690
- programId: constants_1.SQUADS_PROGRAM_ID,
691
- });
692
- return multisigPda;
693
- }
694
- async initializeParentDAO(admin, parentAdmin, name, baseMint, quoteMint, treasuryCosigner, pool, poolType, options) {
695
- const [daoPda] = this.deriveDAOPDA(name);
696
- const [moderatorPda] = this.deriveModeratorPDA(name);
697
- const [mintCreateKeyPda] = this.deriveMintCreateKeyPDA(daoPda, name);
698
- // Derive Squads accounts (single RPC call)
699
- const squadsConfig = await this.fetchSquadsProgramConfig();
700
- const treasuryMultisigPda = this.deriveMultisigPda(daoPda);
701
- const mintMultisigPda = this.deriveMultisigPda(mintCreateKeyPda);
702
- const builder = (0, instructions_1.initializeParentDAO)(this.program, admin, parentAdmin, daoPda, moderatorPda, baseMint, quoteMint, squadsConfig.programConfig, squadsConfig.programConfigTreasury, treasuryMultisigPda, mintMultisigPda, mintCreateKeyPda, constants_1.SQUADS_PROGRAM_ID, name, treasuryCosigner, pool, poolType).preInstructions(this.maybeAddComputeBudget(options));
703
- return {
704
- builder,
705
- daoPda,
706
- moderatorPda,
707
- treasuryMultisig: treasuryMultisigPda,
708
- mintMultisig: mintMultisigPda,
709
- };
710
- }
711
- async initializeChildDAO(admin, parentAdmin, parentDaoName, name, tokenMint, treasuryCosigner, options) {
712
- const [daoPda] = this.deriveDAOPDA(name);
713
- const [parentDaoPda] = this.deriveDAOPDA(parentDaoName);
714
- const [mintCreateKeyPda] = this.deriveMintCreateKeyPDA(daoPda, name);
715
- // Derive Squads accounts (single RPC call)
716
- const squadsConfig = await this.fetchSquadsProgramConfig();
717
- const treasuryMultisigPda = this.deriveMultisigPda(daoPda);
718
- const mintMultisigPda = this.deriveMultisigPda(mintCreateKeyPda);
719
- const builder = (0, instructions_1.initializeChildDAO)(this.program, admin, parentAdmin, daoPda, parentDaoPda, tokenMint, squadsConfig.programConfig, squadsConfig.programConfigTreasury, treasuryMultisigPda, mintMultisigPda, mintCreateKeyPda, constants_1.SQUADS_PROGRAM_ID, name, treasuryCosigner).preInstructions(this.maybeAddComputeBudget(options));
720
- return {
721
- builder,
722
- daoPda,
723
- parentDaoPda,
724
- treasuryMultisig: treasuryMultisigPda,
725
- mintMultisig: mintMultisigPda,
726
- };
727
- }
728
- async upgradeDAO(admin, parentAdmin, daoName, parentDaoName, baseMint, quoteMint, pool, poolType, options) {
729
- const [daoPda] = this.deriveDAOPDA(daoName);
730
- const [parentDaoPda] = this.deriveDAOPDA(parentDaoName);
731
- const [moderatorPda] = this.deriveModeratorPDA(daoName);
732
- const builder = (0, instructions_1.upgradeDAO)(this.program, admin, parentAdmin, daoPda, parentDaoPda, moderatorPda, baseMint, quoteMint, pool, poolType).preInstructions(this.maybeAddComputeBudget(options));
733
- return { builder, daoPda, moderatorPda };
734
- }
735
- async addHistoricalParentDAO(admin, name, baseMint, quoteMint, treasuryMultisig, mintAuthMultisig, cosigner, pool, poolType, proposalIdCounter, adminPubkey, options) {
736
- const [daoPda] = this.deriveDAOPDA(name);
737
- const [moderatorPda] = this.deriveModeratorPDA(name);
738
- const builder = (0, instructions_1.addHistoricalParentDAO)(this.program, admin, daoPda, moderatorPda, treasuryMultisig, mintAuthMultisig, baseMint, quoteMint, name, cosigner, pool, poolType, proposalIdCounter, adminPubkey).preInstructions(this.maybeAddComputeBudget(options));
739
- return {
740
- builder,
741
- daoPda,
742
- moderatorPda,
743
- };
744
- }
745
- async transferAdmin(admin, name, newAdmin, options) {
746
- const [daoPda] = this.deriveDAOPDA(name);
747
- const [moderatorPda] = this.deriveModeratorPDA(name);
748
- const builder = (0, instructions_1.transferAdmin)(this.program, admin, daoPda, moderatorPda, newAdmin).preInstructions(this.maybeAddComputeBudget(options));
749
- return {
750
- builder,
751
- daoPda,
752
- moderatorPda,
753
- };
754
- }
755
- }
756
- exports.FutarchyClient = FutarchyClient;
757
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Z1dGFyY2h5L2NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFSCw4Q0FBZ0U7QUFDaEUsNkNBVXlCO0FBQ3pCLGlEQUsyQjtBQUMzQiwyQ0FBNEQ7QUFTNUQsbUNBV2lCO0FBQ2pCLGlEQWF3QjtBQUd4QixvQ0FBeUY7QUFDekYsZ0NBQXNHO0FBRXRHLDRDQUFnRDtBQUNoRCx5REFBMkM7QUFFM0MsTUFBTSxxQkFBcUIsR0FBRyxNQUFPLENBQUM7QUFFdEMsTUFBYSxjQUFjO0lBT3pCLFlBQVksUUFBd0IsRUFBRSxTQUFxQixFQUFFLFlBQXFCO1FBQ2hGLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxJQUFJLHNCQUFVLENBQUM7UUFDekMsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLGdCQUFPLENBQUMsa0JBQXVCLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLG1CQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdkMsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLGVBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNuQyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsWUFBWSxJQUFJLHFCQUFxQixDQUFDO0lBQ25FLENBQUM7SUFFRCxpQkFBaUI7SUFFakIsWUFBWSxDQUFDLElBQVk7UUFDdkIsT0FBTyxJQUFBLG9CQUFZLEVBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQsa0JBQWtCLENBQUMsSUFBWTtRQUM3QixPQUFPLElBQUEsMEJBQWtCLEVBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBRUQsaUJBQWlCLENBQUMsU0FBb0IsRUFBRSxV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QU0sT0FBTyxHQUFHLElBQUEscUNBQXNCLEVBQ3BDLElBQUksQ0FBQyxPQUFPLEVBQ1osS0FBSyxFQUNMLE1BQU0sRUFDTixZQUFZLEVBQ1osZ0JBQWdCLEVBQ2hCLGdCQUFnQixFQUNoQixRQUFRLEVBQ1IsU0FBUyxFQUNULElBQUksRUFDSixRQUFRLEVBQ1IsSUFBSSxFQUNKLFFBQVEsRUFDUixpQkFBaUIsRUFDakIsV0FBVyxDQUNaLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBRXZELE9BQU87WUFDTCxPQUFPO1lBQ1AsTUFBTTtZQUNOLFlBQVk7U0FDYixDQUFDO0lBQ0osQ0FBQztJQUVELEtBQUssQ0FBQyxhQUFhLENBQ2pCLEtBQWdCLEVBQ2hCLElBQVksRUFDWixRQUFtQixFQUNuQixPQUFtQjtRQUVuQixNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QyxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXJELE1BQU0sT0FBTyxHQUFHLElBQUEsNEJBQWEsRUFDM0IsSUFBSSxDQUFDLE9BQU8sRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksRUFDWixRQUFRLENBQ1QsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFFdkQsT0FBTztZQUNMLE9BQU87WUFDUCxNQUFNO1lBQ04sWUFBWTtTQUNiLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUE1a0NELHdDQTRrQ0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogSGlnaC1sZXZlbCBjbGllbnQgZm9yIHRoZSBGdXRhcmNoeSBwcm9ncmFtLlxuICogSGFuZGxlcyBhY2NvdW50IGRlcml2YXRpb24sIGluc3RydWN0aW9uIGJ1aWxkaW5nLCBhbmQgdHJhbnNhY3Rpb24gY29tcG9zaXRpb24uXG4gKi9cblxuaW1wb3J0IHsgUHJvZ3JhbSwgQW5jaG9yUHJvdmlkZXIsIEJOIH0gZnJvbSBcIkBjb3JhbC14eXovYW5jaG9yXCI7XG5pbXBvcnQge1xuICBQdWJsaWNLZXksXG4gIENvbXB1dGVCdWRnZXRQcm9ncmFtLFxuICBBZGRyZXNzTG9va3VwVGFibGVQcm9ncmFtLFxuICBBZGRyZXNzTG9va3VwVGFibGVBY2NvdW50LFxuICBTeXN0ZW1Qcm9ncmFtLFxuICBUcmFuc2FjdGlvbixcbiAgVHJhbnNhY3Rpb25JbnN0cnVjdGlvbixcbiAgVHJhbnNhY3Rpb25NZXNzYWdlLFxuICBWZXJzaW9uZWRUcmFuc2FjdGlvbixcbn0gZnJvbSBcIkBzb2xhbmEvd2ViMy5qc1wiO1xuaW1wb3J0IHtcbiAgZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmMsXG4gIFRPS0VOX1BST0dSQU1fSUQsXG4gIEFTU09DSUFURURfVE9LRU5fUFJPR1JBTV9JRCxcbiAgY3JlYXRlQXNzb2NpYXRlZFRva2VuQWNjb3VudElkZW1wb3RlbnRJbnN0cnVjdGlvbixcbn0gZnJvbSBcIkBzb2xhbmEvc3BsLXRva2VuXCI7XG5pbXBvcnQgeyBQUk9HUkFNX0lELCBTUVVBRFNfUFJPR1JBTV9JRCB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHtcbiAgRnV0YXJjaHksXG4gIERBT0FjY291bnQsXG4gIE1vZGVyYXRvckFjY291bnQsXG4gIFByb3Bvc2FsQWNjb3VudCxcbiAgUHJvcG9zYWxQYXJhbXMsXG4gIFBvb2xUeXBlLFxufSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHtcbiAgZGVyaXZlREFPUERBLFxuICBkZXJpdmVNb2RlcmF0b3JQREEsXG4gIGRlcml2ZVByb3Bvc2FsUERBLFxuICBkZXJpdmVNaW50Q3JlYXRlS2V5UERBLFxuICBmZXRjaERBT0FjY291bnQsXG4gIGZldGNoTW9kZXJhdG9yQWNjb3VudCxcbiAgZmV0Y2hQcm9wb3NhbEFjY291bnQsXG4gIHBhcnNlUHJvcG9zYWxTdGF0ZSxcbiAgaXNQcm9wb3NhbEV4cGlyZWQsXG4gIGdldFRpbWVSZW1haW5pbmcsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQge1xuICBpbml0aWFsaXplTW9kZXJhdG9yLFxuICBpbml0aWFsaXplUHJvcG9zYWwsXG4gIGFkZE9wdGlvbixcbiAgbGF1bmNoUHJvcG9zYWwsXG4gIGZpbmFsaXplUHJvcG9zYWwsXG4gIHJlZGVlbUxpcXVpZGl0eSxcbiAgYWRkSGlzdG9yaWNhbFByb3Bvc2FsLFxuICBpbml0aWFsaXplUGFyZW50REFPLFxuICBpbml0aWFsaXplQ2hpbGREQU8sXG4gIHVwZ3JhZGVEQU8sXG4gIGFkZEhpc3RvcmljYWxQYXJlbnREQU8sXG4gIHRyYW5zZmVyQWRtaW4sXG59IGZyb20gXCIuL2luc3RydWN0aW9uc1wiO1xuaW1wb3J0IHsgVHhPcHRpb25zIH0gZnJvbSBcIi4uL3V0aWxzXCI7XG5cbmltcG9ydCB7IFZhdWx0Q2xpZW50LCBkZXJpdmVWYXVsdFBEQSwgZGVyaXZlQ29uZGl0aW9uYWxNaW50LCBWYXVsdFR5cGUgfSBmcm9tIFwiLi4vdmF1bHRcIjtcbmltcG9ydCB7IEFNTUNsaWVudCwgZGVyaXZlUG9vbFBEQSwgZGVyaXZlUmVzZXJ2ZVBEQSwgZGVyaXZlRmVlVmF1bHRQREEsIEZFRV9BVVRIT1JJVFkgfSBmcm9tIFwiLi4vYW1tXCI7XG5cbmltcG9ydCB7IEZ1dGFyY2h5SURMIH0gZnJvbSBcIi4uL2dlbmVyYXRlZC9pZGxzXCI7XG5pbXBvcnQgKiBhcyBtdWx0aXNpZyBmcm9tIFwiQHNxZHMvbXVsdGlzaWdcIjtcblxuY29uc3QgREVGQVVMVF9DT01QVVRFX1VOSVRTID0gNTAwXzAwMDtcblxuZXhwb3J0IGNsYXNzIEZ1dGFyY2h5Q2xpZW50IHtcbiAgcHVibGljIHByb2dyYW06IFByb2dyYW08RnV0YXJjaHk+O1xuICBwdWJsaWMgcHJvZ3JhbUlkOiBQdWJsaWNLZXk7XG4gIHB1YmxpYyB2YXVsdDogVmF1bHRDbGllbnQ7XG4gIHB1YmxpYyBhbW06IEFNTUNsaWVudDtcbiAgcHJpdmF0ZSBkZWZhdWx0Q29tcHV0ZVVuaXRzOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IocHJvdmlkZXI6IEFuY2hvclByb3ZpZGVyLCBwcm9ncmFtSWQ/OiBQdWJsaWNLZXksIGNvbXB1dGVVbml0cz86IG51bWJlcikge1xuICAgIHRoaXMucHJvZ3JhbUlkID0gcHJvZ3JhbUlkID8/IFBST0dSQU1fSUQ7XG4gICAgdGhpcy5wcm9ncmFtID0gbmV3IFByb2dyYW0oRnV0YXJjaHlJREwgYXMgRnV0YXJjaHksIHByb3ZpZGVyKTtcbiAgICB0aGlzLnZhdWx0ID0gbmV3IFZhdWx0Q2xpZW50KHByb3ZpZGVyKTtcbiAgICB0aGlzLmFtbSA9IG5ldyBBTU1DbGllbnQocHJvdmlkZXIpO1xuICAgIHRoaXMuZGVmYXVsdENvbXB1dGVVbml0cyA9IGNvbXB1dGVVbml0cyA/PyBERUZBVUxUX0NPTVBVVEVfVU5JVFM7XG4gIH1cblxuICAvKiBQREEgSGVscGVycyAqL1xuXG4gIGRlcml2ZURBT1BEQShuYW1lOiBzdHJpbmcpOiBbUHVibGljS2V5LCBudW1iZXJdIHtcbiAgICByZXR1cm4gZGVyaXZlREFPUERBKG5hbWUsIHRoaXMucHJvZ3JhbUlkKTtcbiAgfVxuXG4gIGRlcml2ZU1vZGVyYXRvclBEQShuYW1lOiBzdHJpbmcpOiBbUHVibGljS2V5LCBudW1iZXJdIHtcbiAgICByZXR1cm4gZGVyaXZlTW9kZXJhdG9yUERBKG5hbWUsIHRoaXMucHJvZ3JhbUlkKTtcbiAgfVxuXG4gIGRlcml2ZVByb3Bvc2FsUERBKG1vZGVyYXRvcjogUHVibGljS2V5LCBwcm9wb3NhbElkOiBudW1iZXIpOiBbUHVibGljS2V5LCBudW1iZXJdIHtcbiAgICByZXR1cm4gZGVyaXZlUHJvcG9zYWxQREEobW9kZXJhdG9yLCBwcm9wb3NhbElkLCB0aGlzLnByb2dyYW1JZCk7XG4gIH1cblxuICAvKiBGZXRjaGVycyAqL1xuXG4gIGFzeW5jIGZldGNoREFPKGRhb1BkYTogUHVibGljS2V5KTogUHJvbWlzZTxEQU9BY2NvdW50PiB7XG4gICAgcmV0dXJuIGZldGNoREFPQWNjb3VudCh0aGlzLnByb2dyYW0sIGRhb1BkYSk7XG4gIH1cblxuICBhc3luYyBmZXRjaE1vZGVyYXRvcihtb2RlcmF0b3JQZGE6IFB1YmxpY0tleSk6IFByb21pc2U8TW9kZXJhdG9yQWNjb3VudD4ge1xuICAgIHJldHVybiBmZXRjaE1vZGVyYXRvckFjY291bnQodGhpcy5wcm9ncmFtLCBtb2RlcmF0b3JQZGEpO1xuICB9XG5cbiAgYXN5bmMgZmV0Y2hQcm9wb3NhbChwcm9wb3NhbFBkYTogUHVibGljS2V5KTogUHJvbWlzZTxQcm9wb3NhbEFjY291bnQ+IHtcbiAgICByZXR1cm4gZmV0Y2hQcm9wb3NhbEFjY291bnQodGhpcy5wcm9ncmFtLCBwcm9wb3NhbFBkYSk7XG4gIH1cblxuICAvKiBQcm9wb3NhbCBIZWxwZXJzICovXG5cbiAgaXNQcm9wb3NhbEV4cGlyZWQocHJvcG9zYWw6IFByb3Bvc2FsQWNjb3VudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBpc1Byb3Bvc2FsRXhwaXJlZChwcm9wb3NhbCk7XG4gIH1cblxuICBnZXRUaW1lUmVtYWluaW5nKHByb3Bvc2FsOiBQcm9wb3NhbEFjY291bnQpOiBudW1iZXIge1xuICAgIHJldHVybiBnZXRUaW1lUmVtYWluaW5nKHByb3Bvc2FsKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q29tcHV0ZVVuaXRzKG9wdGlvbnM/OiBUeE9wdGlvbnMpOiBudW1iZXIge1xuICAgIHJldHVybiBvcHRpb25zPy5jb21wdXRlVW5pdHMgPz8gdGhpcy5kZWZhdWx0Q29tcHV0ZVVuaXRzO1xuICB9XG5cbiAgcHJpdmF0ZSBtYXliZUFkZENvbXB1dGVCdWRnZXQob3B0aW9ucz86IFR4T3B0aW9ucyk6IFRyYW5zYWN0aW9uSW5zdHJ1Y3Rpb25bXSB7XG4gICAgaWYgKG9wdGlvbnM/LmluY2x1ZGVDdUJ1ZGdldCA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgcmV0dXJuIFtDb21wdXRlQnVkZ2V0UHJvZ3JhbS5zZXRDb21wdXRlVW5pdExpbWl0KHsgdW5pdHM6IHRoaXMuZ2V0Q29tcHV0ZVVuaXRzKG9wdGlvbnMpIH0pXTtcbiAgfVxuXG4gIC8qIEluc3RydWN0aW9uIEJ1aWxkZXJzICovXG5cbiAgYXN5bmMgaW5pdGlhbGl6ZU1vZGVyYXRvcihcbiAgICBhZG1pbjogUHVibGljS2V5LFxuICAgIGJhc2VNaW50OiBQdWJsaWNLZXksXG4gICAgcXVvdGVNaW50OiBQdWJsaWNLZXksXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBUeE9wdGlvbnNcbiAgKSB7XG4gICAgY29uc3QgW21vZGVyYXRvclBkYV0gPSB0aGlzLmRlcml2ZU1vZGVyYXRvclBEQShuYW1lKTtcblxuICAgIGNvbnN0IGJ1aWxkZXIgPSBpbml0aWFsaXplTW9kZXJhdG9yKFxuICAgICAgdGhpcy5wcm9ncmFtLFxuICAgICAgYWRtaW4sXG4gICAgICBiYXNlTWludCxcbiAgICAgIHF1b3RlTWludCxcbiAgICAgIG1vZGVyYXRvclBkYSxcbiAgICAgIG5hbWVcbiAgICApLnByZUluc3RydWN0aW9ucyh0aGlzLm1heWJlQWRkQ29tcHV0ZUJ1ZGdldChvcHRpb25zKSk7XG5cbiAgICByZXR1cm4geyBidWlsZGVyLCBtb2RlcmF0b3JQZGEsIG5hbWUgfTtcbiAgfVxuXG4gIGFzeW5jIGFkZEhpc3RvcmljYWxQcm9wb3NhbChcbiAgICBhZG1pbjogUHVibGljS2V5LFxuICAgIG1vZGVyYXRvclBkYTogUHVibGljS2V5LFxuICAgIG51bU9wdGlvbnM6IG51bWJlcixcbiAgICB3aW5uaW5nSWR4OiBudW1iZXIsXG4gICAgbGVuZ3RoOiBudW1iZXIsXG4gICAgY3JlYXRlZEF0OiBCTiB8IG51bWJlcixcbiAgICBtZXRhZGF0YTogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBUeE9wdGlvbnNcbiAgKSB7XG4gICAgY29uc3QgbW9kZXJhdG9yID0gYXdhaXQgdGhpcy5mZXRjaE1vZGVyYXRvcihtb2RlcmF0b3JQZGEpO1xuICAgIGNvbnN0IHByb3Bvc2FsSWQgPSBtb2RlcmF0b3IucHJvcG9zYWxJZENvdW50ZXI7XG4gICAgY29uc3QgW3Byb3Bvc2FsUGRhXSA9IHRoaXMuZGVyaXZlUHJvcG9zYWxQREEobW9kZXJhdG9yUGRhLCBwcm9wb3NhbElkKTtcblxuICAgIGNvbnN0IGJ1aWxkZXIgPSBhZGRIaXN0b3JpY2FsUHJvcG9zYWwoXG4gICAgICB0aGlzLnByb2dyYW0sXG4gICAgICBhZG1pbixcbiAgICAgIG1vZGVyYXRvclBkYSxcbiAgICAgIHByb3Bvc2FsUGRhLFxuICAgICAgbnVtT3B0aW9ucyxcbiAgICAgIHdpbm5pbmdJZHgsXG4gICAgICBsZW5ndGgsXG4gICAgICBjcmVhdGVkQXQsXG4gICAgICBtZXRhZGF0YVxuICAgICkucHJlSW5zdHJ1Y3Rpb25zKHRoaXMubWF5YmVBZGRDb21wdXRlQnVkZ2V0KG9wdGlvbnMpKTtcblxuICAgIHJldHVybiB7IGJ1aWxkZXIsIHByb3Bvc2FsUGRhLCBwcm9wb3NhbElkIH07XG4gIH1cblxuICBhc3luYyBpbml0aWFsaXplUHJvcG9zYWwoXG4gICAgY3JlYXRvcjogUHVibGljS2V5LFxuICAgIG1vZGVyYXRvclBkYTogUHVibGljS2V5LFxuICAgIHByb3Bvc2FsUGFyYW1zOiBQcm9wb3NhbFBhcmFtcyxcbiAgICBtZXRhZGF0YT86IHN0cmluZyxcbiAgICBvcHRpb25zPzogVHhPcHRpb25zXG4gICkge1xuICAgIGNvbnN0IG1vZGVyYXRvciA9IGF3YWl0IHRoaXMuZmV0Y2hNb2RlcmF0b3IobW9kZXJhdG9yUGRhKTtcbiAgICBjb25zdCBwcm9wb3NhbElkID0gbW9kZXJhdG9yLnByb3Bvc2FsSWRDb3VudGVyO1xuICAgIGNvbnN0IFtwcm9wb3NhbFBkYV0gPSB0aGlzLmRlcml2ZVByb3Bvc2FsUERBKG1vZGVyYXRvclBkYSwgcHJvcG9zYWxJZCk7XG5cbiAgICAvLyBEZXJpdmUgdmF1bHQgUERBIChwcm9wb3NhbCBpcyB0aGUgb3duZXIsIG5vbmNlPXByb3Bvc2FsSWQpXG4gICAgY29uc3QgW3ZhdWx0UGRhXSA9IGRlcml2ZVZhdWx0UERBKHByb3Bvc2FsUGRhLCBwcm9wb3NhbElkLCB0aGlzLnZhdWx0LnByb2dyYW1JZCk7XG5cbiAgICAvLyBEZXJpdmUgY29uZGl0aW9uYWwgbWludHMgZm9yIGluaXRpYWwgMiBvcHRpb25zXG4gICAgY29uc3QgW2NvbmRCYXNlTWludDBdID0gZGVyaXZlQ29uZGl0aW9uYWxNaW50KHZhdWx0UGRhLCBWYXVsdFR5cGUuQmFzZSwgMCwgdGhpcy52YXVsdC5wcm9ncmFtSWQpO1xuICAgIGNvbnN0IFtjb25kQmFzZU1pbnQxXSA9IGRlcml2ZUNvbmRpdGlvbmFsTWludCh2YXVsdFBkYSwgVmF1bHRUeXBlLkJhc2UsIDEsIHRoaXMudmF1bHQucHJvZ3JhbUlkKTtcbiAgICBjb25zdCBbY29uZFF1b3RlTWludDBdID0gZGVyaXZlQ29uZGl0aW9uYWxNaW50KHZhdWx0UGRhLCBWYXVsdFR5cGUuUXVvdGUsIDAsIHRoaXMudmF1bHQucHJvZ3JhbUlkKTtcbiAgICBjb25zdCBbY29uZFF1b3RlTWludDFdID0gZGVyaXZlQ29uZGl0aW9uYWxNaW50KHZhdWx0UGRhLCBWYXVsdFR5cGUuUXVvdGUsIDEsIHRoaXMudmF1bHQucHJvZ3JhbUlkKTtcblxuICAgIC8vIERlcml2ZSBwb29sIFBEQXMgZm9yIGluaXRpYWwgMiBvcHRpb25zIChwcm9wb3NhbCBpcyBhZG1pbiwgbWludEE9Y29uZFF1b3RlLCBtaW50Qj1jb25kQmFzZSlcbiAgICBjb25zdCBbcG9vbDBdID0gZGVyaXZlUG9vbFBEQShwcm9wb3NhbFBkYSwgY29uZFF1b3RlTWludDAsIGNvbmRCYXNlTWludDAsIHRoaXMuYW1tLnByb2dyYW1JZCk7XG4gICAgY29uc3QgW3Bvb2wxXSA9IGRlcml2ZVBvb2xQREEocHJvcG9zYWxQZGEsIGNvbmRRdW90ZU1pbnQxLCBjb25kQmFzZU1pbnQxLCB0aGlzLmFtbS5wcm9ncmFtSWQpO1xuXG4gICAgLy8gRGVyaXZlIHJlc2VydmVzIGFuZCBmZWUgdmF1bHRzXG4gICAgY29uc3QgW3Jlc2VydmVBMF0gPSBkZXJpdmVSZXNlcnZlUERBKHBvb2wwLCBjb25kUXVvdGVNaW50MCwgdGhpcy5hbW0ucHJvZ3JhbUlkKTtcbiAgICBjb25zdCBbcmVzZXJ2ZUIwXSA9IGRlcml2ZVJlc2VydmVQREEocG9vbDAsIGNvbmRCYXNlTWludDAsIHRoaXMuYW1tLnByb2dyYW1JZCk7XG4gICAgY29uc3QgW2ZlZVZhdWx0MF0gPSBkZXJpdmVGZWVWYXVsdFBEQShwb29sMCwgdGhpcy5hbW0ucHJvZ3JhbUlkKTtcbiAgICBjb25zdCBbcmVzZXJ2ZUExXSA9IGRlcml2ZVJlc2VydmVQREEocG9vbDEsIGNvbmRRdW90ZU1pbnQxLCB0aGlzLmFtbS5wcm9ncmFtSWQpO1xuICAgIGNvbnN0IFtyZXNlcnZlQjFdID0gZGVyaXZlUmVzZXJ2ZVBEQShwb29sMSwgY29uZEJhc2VNaW50MSwgdGhpcy5hbW0ucHJvZ3JhbUlkKTtcbiAgICBjb25zdCBbZmVlVmF1bHQxXSA9IGRlcml2ZUZlZVZhdWx0UERBKHBvb2wxLCB0aGlzLmFtbS5wcm9ncmFtSWQpO1xuXG4gICAgLy8gVmF1bHQgdG9rZW4gYWNjb3VudHNcbiAgICBjb25zdCBiYXNlVG9rZW5BY2MgPSBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyhtb2RlcmF0b3IuYmFzZU1pbnQsIHZhdWx0UGRhLCB0cnVlKTtcbiAgICBjb25zdCBxdW90ZVRva2VuQWNjID0gZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmMobW9kZXJhdG9yLnF1b3RlTWludCwgdmF1bHRQZGEsIHRydWUpO1xuXG4gICAgLy8gQnVpbGQgcmVtYWluaW5nIGFjY291bnRzIGluIGV4cGVjdGVkIG9yZGVyIChzZWUgaW5pdGlhbGl6ZV9wcm9wb3NhbC5ycylcbiAgICBjb25zdCByZW1haW5pbmdBY2NvdW50cyA9IFtcbiAgICAgIHsgcHVia2V5OiBtb2RlcmF0b3IuYmFzZU1pbnQsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogZmFsc2UgfSwgICAgICAvLyAwOiBiYXNlX21pbnRcbiAgICAgIHsgcHVia2V5OiBtb2RlcmF0b3IucXVvdGVNaW50LCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IGZhbHNlIH0sICAgICAvLyAxOiBxdW90ZV9taW50XG4gICAgICB7IHB1YmtleTogdmF1bHRQZGEsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LCAgICAgICAgICAgICAgICAgLy8gMjogdmF1bHRcbiAgICAgIHsgcHVia2V5OiBiYXNlVG9rZW5BY2MsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LCAgICAgICAgICAgICAvLyAzOiBiYXNlX3Rva2VuX2FjY1xuICAgICAgeyBwdWJrZXk6IHF1b3RlVG9rZW5BY2MsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LCAgICAgICAgICAgIC8vIDQ6IHF1b3RlX3Rva2VuX2FjY1xuICAgICAgeyBwdWJrZXk6IGNvbmRCYXNlTWludDAsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LCAgICAgICAgICAgIC8vIDU6IGNvbmRfYmFzZV9taW50XzBcbiAgICAgIHsgcHVia2V5OiBjb25kQmFzZU1pbnQxLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSwgICAgICAgICAgICAvLyA2OiBjb25kX2Jhc2VfbWludF8xXG4gICAgICB7IHB1YmtleTogY29uZFF1b3RlTWludDAsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LCAgICAgICAgICAgLy8gNzogY29uZF9xdW90ZV9taW50XzBcbiAgICAgIHsgcHVia2V5OiBjb25kUXVvdGVNaW50MSwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0sICAgICAgICAgICAvLyA4OiBjb25kX3F1b3RlX21pbnRfMVxuICAgICAgeyBwdWJrZXk6IHBvb2wwLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSwgICAgICAgICAgICAgICAgICAgIC8vIDk6IHBvb2xfMFxuICAgICAgeyBwdWJrZXk6IHJlc2VydmVBMCwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0sICAgICAgICAgICAgICAgIC8vIDEwOiByZXNlcnZlX2FfMFxuICAgICAgeyBwdWJrZXk6IHJlc2VydmVCMCwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0sICAgICAgICAgICAgICAgIC8vIDExOiByZXNlcnZlX2JfMFxuICAgICAgeyBwdWJrZXk6IEZFRV9BVVRIT1JJVFksIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogZmFsc2UgfSwgICAgICAgICAgIC8vIDEyOiBmZWVfYXV0aG9yaXR5XG4gICAgICB7IHB1YmtleTogZmVlVmF1bHQwLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSwgICAgICAgICAgICAgICAgLy8gMTM6IGZlZV92YXVsdF8wXG4gICAgICB7IHB1YmtleTogcG9vbDEsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LCAgICAgICAgICAgICAgICAgICAgLy8gMTQ6IHBvb2xfMVxuICAgICAgeyBwdWJrZXk6IHJlc2VydmVBMSwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0sICAgICAgICAgICAgICAgIC8vIDE1OiByZXNlcnZlX2FfMVxuICAgICAgeyBwdWJrZXk6IHJlc2VydmVCMSwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0sICAgICAgICAgICAgICAgIC8vIDE2OiByZXNlcnZlX2JfMVxuICAgICAgeyBwdWJrZXk6IGZlZVZhdWx0MSwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0sICAgICAgICAgICAgICAgIC8vIDE3OiBmZWVfdmF1bHRfMVxuICAgIF07XG5cbiAgICBjb25zdCBidWlsZGVyID0gaW5pdGlhbGl6ZVByb3Bvc2FsKFxuICAgICAgdGhpcy5wcm9ncmFtLFxuICAgICAgY3JlYXRvcixcbiAgICAgIG1vZGVyYXRvclBkYSxcbiAgICAgIHByb3Bvc2FsUGRhLFxuICAgICAgcHJvcG9zYWxQYXJhbXMsXG4gICAgICBtZXRhZGF0YSA/PyBudWxsLFxuICAgICAgcmVtYWluaW5nQWNjb3VudHNcbiAgICApLnByZUluc3RydWN0aW9ucyh0aGlzLm1heWJlQWRkQ29tcHV0ZUJ1ZGdldChvcHRpb25zKSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgYnVpbGRlcixcbiAgICAgIHByb3Bvc2FsUGRhLFxuICAgICAgcHJvcG9zYWxJZCxcbiAgICAgIHZhdWx0UGRhLFxuICAgICAgcG9vbHM6IFtwb29sMCwgcG9vbDFdLFxuICAgICAgY29uZEJhc2VNaW50czogW2NvbmRCYXNlTWludDAsIGNvbmRCYXNlTWludDFdLFxuICAgICAgY29uZFF1b3RlTWludHM6IFtjb25kUXVvdGVNaW50MCwgY29uZFF1b3RlTWludDFdLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBhZGRPcHRpb24oY3JlYXRvcjogUHVibGljS2V5LCBwcm9wb3NhbFBkYTogUHVibGljS2V5LCBvcHRpb25zPzogVHhPcHRpb25zKSB7XG4gICAgY29uc3QgcHJvcG9zYWwgPSBhd2FpdCB0aGlzLmZldGNoUHJvcG9zYWwocHJvcG9zYWxQZGEpO1xuICAgIGNvbnN0IG9wdGlvbkluZGV4ID0gcHJvcG9zYWwubnVtT3B0aW9ucztcblxuICAgIC8vIERlcml2ZSBuZXcgY29uZGl0aW9uYWwgbWludHNcbiAgICBjb25zdCBbY29uZEJhc2VNaW50XSA9IGRlcml2ZUNvbmRpdGlvbmFsTWludChwcm9wb3NhbC52YXVsdCwgVmF1bHRUeXBlLkJhc2UsIG9wdGlvbkluZGV4LCB0aGlzLnZhdWx0LnByb2dyYW1JZCk7XG4gICAgY29uc3QgW2NvbmRRdW90ZU1pbnRdID0gZGVyaXZlQ29uZGl0aW9uYWxNaW50KHByb3Bvc2FsLnZhdWx0LCBWYXVsdFR5cGUuUXVvdGUsIG9wdGlvbkluZGV4LCB0aGlzLnZhdWx0LnByb2dyYW1JZCk7XG5cbiAgICAvLyBEZXJpdmUgcG9vbCBQREFcbiAgICBjb25zdCBbcG9vbF0gPSBkZXJpdmVQb29sUERBKHByb3Bvc2FsUGRhLCBjb25kUXVvdGVNaW50LCBjb25kQmFzZU1pbnQsIHRoaXMuYW1tLnByb2dyYW1JZCk7XG4gICAgY29uc3QgW3Jlc2VydmVBXSA9IGRlcml2ZVJlc2VydmVQREEocG9vbCwgY29uZFF1b3RlTWludCwgdGhpcy5hbW0ucHJvZ3JhbUlkKTtcbiAgICBjb25zdCBbcmVzZXJ2ZUJdID0gZGVyaXZlUmVzZXJ2ZVBEQShwb29sLCBjb25kQmFzZU1pbnQsIHRoaXMuYW1tLnByb2dyYW1JZCk7XG4gICAgY29uc3QgW2ZlZVZhdWx0XSA9IGRlcml2ZUZlZVZhdWx0UERBKHBvb2wsIHRoaXMuYW1tLnByb2dyYW1JZCk7XG5cbiAgICAvLyBCdWlsZCByZW1haW5pbmcgYWNjb3VudHMgKHNlZSBhZGRfb3B0aW9uLnJzKVxuICAgIGNvbnN0IHJlbWFpbmluZ0FjY291bnRzID0gW1xuICAgICAgeyBwdWJrZXk6IHByb3Bvc2FsLnZhdWx0LCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSwgICAgICAgICAgIC8vIDA6IHZhdWx0XG4gICAgICB7IHB1YmtleTogY29uZEJhc2VNaW50LCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSwgICAgICAgICAgICAgLy8gMTogY29uZF9iYXNlX21pbnRcbiAgICAgIHsgcHVia2V5OiBjb25kUXVvdGVNaW50LCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSwgICAgICAgICAgICAvLyAyOiBjb25kX3F1b3RlX21pbnRcbiAgICAgIHsgcHVia2V5OiBwb29sLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSwgICAgICAgICAgICAgICAgICAgICAvLyAzOiBwb29sXG4gICAgICB7IHB1YmtleTogcmVzZXJ2ZUEsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LCAgICAgICAgICAgICAgICAgLy8gNDogcmVzZXJ2ZV9hXG4gICAgICB7IHB1YmtleTogcmVzZXJ2ZUIsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LCAgICAgICAgICAgICAgICAgLy8gNTogcmVzZXJ2ZV9iXG4gICAgICB7IHB1YmtleTogRkVFX0FVVEhPUklUWSwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiBmYWxzZSB9LCAgICAgICAgICAgLy8gNjogZmVlX2F1dGhvcml0eVxuICAgICAgeyBwdWJrZXk6IGZlZVZhdWx0LCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSwgICAgICAgICAgICAgICAgIC8vIDc6IGZlZV92YXVsdFxuICAgIF07XG5cbiAgICBjb25zdCBidWlsZGVyID0gYWRkT3B0aW9uKHRoaXMucHJvZ3JhbSwgY3JlYXRvciwgcHJvcG9zYWxQZGEsIHJlbWFpbmluZ0FjY291bnRzKVxuICAgICAgLnByZUluc3RydWN0aW9ucyh0aGlzLm1heWJlQWRkQ29tcHV0ZUJ1ZGdldChvcHRpb25zKSk7XG5cbiAgICByZXR1cm4geyBidWlsZGVyLCBvcHRpb25JbmRleCwgcG9vbCwgY29uZEJhc2VNaW50LCBjb25kUXVvdGVNaW50IH07XG4gIH1cblxuICBhc3luYyBsYXVuY2hQcm9wb3NhbChcbiAgICBjcmVhdG9yOiBQdWJsaWNLZXksXG4gICAgcHJvcG9zYWxQZGE6IFB1YmxpY0tleSxcbiAgICBiYXNlQW1vdW50OiBCTiB8IG51bWJlcixcbiAgICBxdW90ZUFtb3VudDogQk4gfCBudW1iZXIsXG4gICAgb3B0aW9ucz86IFR4T3B0aW9uc1xuICApIHtcbiAgICBjb25zdCBwcm9wb3NhbCA9IGF3YWl0IHRoaXMuZmV0Y2hQcm9wb3NhbChwcm9wb3NhbFBkYSk7XG4gICAgY29uc3QgdmF1bHQgPSBhd2FpdCB0aGlzLnZhdWx0LmZldGNoVmF1bHQocHJvcG9zYWwudmF1bHQpO1xuICAgIGNvbnN0IG51bU9wdGlvbnMgPSBwcm9wb3NhbC5udW1PcHRpb25zO1xuXG4gICAgLy8gU2xpY2UgYXJyYXlzIHRvIG51bU9wdGlvbnMgKGZpeGVkLXNpemUgYXJyYXlzIGZyb20gUnVzdCBpbmNsdWRlIGVtcHR5IHNsb3RzKVxuICAgIGNvbnN0IGNvbmRCYXNlTWludHMgPSB2YXVsdC5jb25kQmFzZU1pbnRzLnNsaWNlKDAsIG51bU9wdGlvbnMpO1xuICAgIGNvbnN0IGNvbmRRdW90ZU1pbnRzID0gdmF1bHQuY29uZFF1b3RlTWludHMuc2xpY2UoMCwgbnVtT3B0aW9ucyk7XG5cbiAgICAvLyBQcmUtY3JlYXRlIGNvbmRpdGlvbmFsIEFUQXMgZm9yIDMrIG9wdGlvbnMgdG8gYXZvaWQgZXhjZWVkaW5nIHRoZVxuICAgIC8vIDY0IGluc3RydWN0aW9uIHRyYWNlIGxpbWl0LiBFYWNoIEFUQSBjcmVhdGlvbiB2aWEgdmF1bHQgZGVwb3NpdCBhZGRzXG4gICAgLy8gNSBpbm5lciBpbnN0cnVjdGlvbnM7IHdpdGggNCBvcHRpb25zIHRoYXQncyA0MCBleHRyYSBpbnN0cnVjdGlvbnMuXG4gICAgY29uc3Qgc2hvdWxkRW5zdXJlQVRBcyA9IG9wdGlvbnM/LmVuc3VyZUFUQXMgPz8gKG51bU9wdGlvbnMgPj0gMyk7XG4gICAgaWYgKHNob3VsZEVuc3VyZUFUQXMpIHtcbiAgICAgIGF3YWl0IHRoaXMuX2NyZWF0ZUNvbmRpdGlvbmFsQVRBcyhjcmVhdG9yLCBjb25kQmFzZU1pbnRzLCBjb25kUXVvdGVNaW50cyk7XG4gICAgfVxuICAgIGNvbnN0IHBvb2xzID0gcHJvcG9zYWwucG9vbHMuc2xpY2UoMCwgbnVtT3B0aW9ucyk7XG5cbiAgICAvLyBEZXJpdmUgYWxsIHVzZXIgY29uZGl0aW9uYWwgdG9rZW4gQVRBc1xuICAgIGNvbnN0IHVzZXJDb25kQmFzZUFUQXMgPSBjb25kQmFzZU1pbnRzLm1hcCgobSkgPT4gZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmMobSwgY3JlYXRvcikpO1xuICAgIGNvbnN0IHVzZXJDb25kUXVvdGVBVEFzID0gY29uZFF1b3RlTWludHMubWFwKChtKSA9PiBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyhtLCBjcmVhdG9yKSk7XG5cbiAgICAvLyBEZXJpdmUgcmVzZXJ2ZSBhY2NvdW50cyBmb3IgZWFjaCBwb29sXG4gICAgY29uc3QgcmVzZXJ2ZXNBOiBQdWJsaWNLZXlbXSA9IFtdO1xuICAgIGNvbnN0IHJlc2VydmVzQjogUHVibGljS2V5W10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bU9wdGlvbnM7IGkrKykge1xuICAgICAgY29uc3QgW3Jlc0FdID0gZGVyaXZlUmVzZXJ2ZVBEQShwb29sc1tpXSwgY29uZFF1b3RlTWludHNbaV0sIHRoaXMuYW1tLnByb2dyYW1JZCk7XG4gICAgICBjb25zdCBbcmVzQl0gPSBkZXJpdmVSZXNlcnZlUERBKHBvb2xzW2ldLCBjb25kQmFzZU1pbnRzW2ldLCB0aGlzLmFtbS5wcm9ncmFtSWQpO1xuICAgICAgcmVzZXJ2ZXNBLnB1c2gocmVzQSk7XG4gICAgICByZXNlcnZlc0IucHVzaChyZXNCKTtcbiAgICB9XG5cbiAgICAvLyBCdWlsZCByZW1haW5pbmcgYWNjb3VudHMgKHNlZSBsYXVuY2hfcHJvcG9zYWwucnMpXG4gICAgLy8gTGF5b3V0OiA2IGZpeGVkICsgNypOIHZhcmlhYmxlXG4gICAgY29uc3QgcmVtYWluaW5nQWNjb3VudHM6IHsgcHVia2V5OiBQdWJsaWNLZXk7IGlzU2lnbmVyOiBib29sZWFuOyBpc1dyaXRhYmxlOiBib29sZWFuIH1bXSA9IFtcbiAgICAgIHsgcHVia2V5OiB2YXVsdC5iYXNlTWludC5hZGRyZXNzLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IGZhbHNlIH0sICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gMDogYmFzZV9taW50XG4gICAgICB7IHB1YmtleTogdmF1bHQucXVvdGVNaW50LmFkZHJlc3MsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogZmFsc2UgfSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDE6IHF1b3RlX21pbnRcbiAgICAgIHsgcHVia2V5OiBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh2YXVsdC5iYXNlTWludC5hZGRyZXNzLCBwcm9wb3NhbC52YXVsdCwgdHJ1ZSksIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LCAgIC8vIDI6IHZhdWx0X2Jhc2VfYXRhXG4gICAgICB7IHB1YmtleTogZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmModmF1bHQucXVvdGVNaW50LmFkZHJlc3MsIHByb3Bvc2FsLnZhdWx0LCB0cnVlKSwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0sICAvLyAzOiB2YXVsdF9xdW90ZV9hdGFcbiAgICAgIHsgcHVia2V5OiBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh2YXVsdC5iYXNlTWludC5hZGRyZXNzLCBjcmVhdG9yKSwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0sICAvLyA0OiB1c2VyX2Jhc2VfYXRhXG4gICAgICB7IHB1YmtleTogZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmModmF1bHQucXVvdGVNaW50LmFkZHJlc3MsIGNyZWF0b3IpLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSwgLy8gNTogdXNlcl9xdW90ZV9hdGFcbiAgICBdO1xuXG4gICAgLy8gNi4uNitOOiBjb25kX2Jhc2VfbWludHNcbiAgICBmb3IgKGNvbnN0IG1pbnQgb2YgY29uZEJhc2VNaW50cykge1xuICAgICAgcmVtYWluaW5nQWNjb3VudHMucHVzaCh7IHB1YmtleTogbWludCwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0pO1xuICAgIH1cbiAgICAvLyA2K04uLjYrMk46IGNvbmRfcXVvdGVfbWludHNcbiAgICBmb3IgKGNvbnN0IG1pbnQgb2YgY29uZFF1b3RlTWludHMpIHtcbiAgICAgIHJlbWFpbmluZ0FjY291bnRzLnB1c2goeyBwdWJrZXk6IG1pbnQsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9KTtcbiAgICB9XG4gICAgLy8gNisyTi4uNiszTjogdXNlcl9jb25kX2Jhc2VfYXRhc1xuICAgIGZvciAoY29uc3QgYXRhIG9mIHVzZXJDb25kQmFzZUFUQXMpIHtcbiAgICAgIHJlbWFpbmluZ0FjY291bnRzLnB1c2goeyBwdWJrZXk6IGF0YSwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0pO1xuICAgIH1cbiAgICAvLyA2KzNOLi42KzROOiB1c2VyX2NvbmRfcXVvdGVfYXRhc1xuICAgIGZvciAoY29uc3QgYXRhIG9mIHVzZXJDb25kUXVvdGVBVEFzKSB7XG4gICAgICByZW1haW5pbmdBY2NvdW50cy5wdXNoKHsgcHVia2V5OiBhdGEsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9KTtcbiAgICB9XG4gICAgLy8gNis0Ti4uNis1TjogcG9vbHNcbiAgICBmb3IgKGNvbnN0IHBvb2wgb2YgcG9vbHMpIHtcbiAgICAgIHJlbWFpbmluZ0FjY291bnRzLnB1c2goeyBwdWJrZXk6IHBvb2wsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9KTtcbiAgICB9XG4gICAgLy8gNis1Ti4uNis2TjogcmVzZXJ2ZXNfYVxuICAgIGZvciAoY29uc3QgcmVzIG9mIHJlc2VydmVzQSkge1xuICAgICAgcmVtYWluaW5nQWNjb3VudHMucHVzaCh7IHB1YmtleTogcmVzLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSk7XG4gICAgfVxuICAgIC8vIDYrNk4uLjYrN046IHJlc2VydmVzX2JcbiAgICBmb3IgKGNvbnN0IHJlcyBvZiByZXNlcnZlc0IpIHtcbiAgICAgIHJlbWFpbmluZ0FjY291bnRzLnB1c2goeyBwdWJrZXk6IHJlcywgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGJ1aWxkZXIgPSBsYXVuY2hQcm9wb3NhbChcbiAgICAgIHRoaXMucHJvZ3JhbSxcbiAgICAgIGNyZWF0b3IsXG4gICAgICBwcm9wb3NhbFBkYSxcbiAgICAgIHByb3Bvc2FsLnZhdWx0LFxuICAgICAgYmFzZUFtb3VudCxcbiAgICAgIHF1b3RlQW1vdW50LFxuICAgICAgcmVtYWluaW5nQWNjb3VudHNcbiAgICApLnByZUluc3RydWN0aW9ucyh0aGlzLm1heWJlQWRkQ29tcHV0ZUJ1ZGdldChvcHRpb25zKSk7XG5cbiAgICByZXR1cm4geyBidWlsZGVyIH07XG4gIH1cblxuICAvKipcbiAgICogUHJlLWNyZWF0ZXMgYWxsIGNvbmRpdGlvbmFsIHRva2VuIEFUQXMgZm9yIGEgdXNlciBiZWZvcmUgbGF1bmNoaW5nIGEgcHJvcG9zYWwuXG4gICAqXG4gICAqIFRoaXMgaXMgUkVRVUlSRUQgZm9yIHByb3Bvc2FscyB3aXRoIDMrIG9wdGlvbnMgdG8gYXZvaWQgZXhjZWVkaW5nIFNvbGFuYSdzXG4gICAqIG1heCBpbnN0cnVjdGlvbiB0cmFjZSBsZW5ndGggbGltaXQgKDY0IGluc3RydWN0aW9ucykuIFRoZSB2YXVsdCdzIGRlcG9zaXQgQ1BJXG4gICAqIGNyZWF0ZXMgQVRBcyBvbi10aGUtZmx5LCBlYWNoIHJlcXVpcmluZyA1IGlubmVyIGluc3RydWN0aW9ucy4gRm9yIDQgb3B0aW9uczpcbiAgICogOCBBVEFzIMOXIDUgPSA0MCBleHRyYSBpbnN0cnVjdGlvbnMsIHB1c2hpbmcgdGhlIHRvdGFsIG92ZXIgNjQuXG4gICAqXG4gICAqIFByZS1jcmVhdGluZyBBVEFzIGVsaW1pbmF0ZXMgdGhpcyBvdmVyaGVhZCwgcmVkdWNpbmcgdGhlIHRyYWNlIHRvIH4zMiBpbnN0cnVjdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSBjcmVhdG9yIC0gVGhlIHVzZXIgd2hvIHdpbGwgcmVjZWl2ZSBjb25kaXRpb25hbCB0b2tlbnNcbiAgICogQHBhcmFtIHByb3Bvc2FsUGRhIC0gVGhlIHByb3Bvc2FsIFBEQSAobXVzdCBiZSBpbml0aWFsaXplZCBidXQgbm90IGxhdW5jaGVkKVxuICAgKiBAcmV0dXJucyBUcmFuc2FjdGlvbiBzaWduYXR1cmVcbiAgICovXG4gIGFzeW5jIGVuc3VyZUNvbmRpdGlvbmFsQVRBcyhcbiAgICBjcmVhdG9yOiBQdWJsaWNLZXksXG4gICAgcHJvcG9zYWxQZGE6IFB1YmxpY0tleSxcbiAgKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBwcm9wb3NhbCA9IGF3YWl0IHRoaXMuZmV0Y2hQcm9wb3NhbChwcm9wb3NhbFBkYSk7XG4gICAgY29uc3QgdmF1bHQgPSBhd2FpdCB0aGlzLnZhdWx0LmZldGNoVmF1bHQocHJvcG9zYWwudmF1bHQpO1xuICAgIGNvbnN0IGNvbmRCYXNlTWludHMgPSB2YXVsdC5jb25kQmFzZU1pbnRzLnNsaWNlKDAsIHByb3Bvc2FsLm51bU9wdGlvbnMpO1xuICAgIGNvbnN0IGNvbmRRdW90ZU1pbnRzID0gdmF1bHQuY29uZFF1b3RlTWludHMuc2xpY2UoMCwgcHJvcG9zYWwubnVtT3B0aW9ucyk7XG4gICAgcmV0dXJuIHRoaXMuX2NyZWF0ZUNvbmRpdGlvbmFsQVRBcyhjcmVhdG9yLCBjb25kQmFzZU1pbnRzLCBjb25kUXVvdGVNaW50cyk7XG4gIH1cblxuICAvKipcbiAgICogSW50ZXJuYWwgaGVscGVyIHRvIGNyZWF0ZSBjb25kaXRpb25hbCBBVEFzIGdpdmVuIG1pbnQgYXJyYXlzLlxuICAgKiBVc2VkIGJ5IGJvdGggZW5zdXJlQ29uZGl0aW9uYWxBVEFzIGFuZCBsYXVuY2hQcm9wb3NhbCB0byBhdm9pZCByZWR1bmRhbnQgZmV0Y2hlcy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgX2NyZWF0ZUNvbmRpdGlvbmFsQVRBcyhcbiAgICBjcmVhdG9yOiBQdWJsaWNLZXksXG4gICAgY29uZEJhc2VNaW50czogUHVibGljS2V5W10sXG4gICAgY29uZFF1b3RlTWludHM6IFB1YmxpY0tleVtdLFxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHByb3ZpZGVyID0gdGhpcy5wcm9ncmFtLnByb3ZpZGVyIGFzIEFuY2hvclByb3ZpZGVyO1xuXG4gICAgLy8gQnVpbGQgQVRBIGNyZWF0aW9uIGluc3RydWN0aW9ucyAoaWRlbXBvdGVudCAtIHdvbid0IGZhaWwgaWYgZXhpc3RzKVxuICAgIGNvbnN0IGluc3RydWN0aW9uczogVHJhbnNhY3Rpb25JbnN0cnVjdGlvbltdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb25kQmFzZU1pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCB1c2VyQ29uZEJhc2VBdGEgPSBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyhjb25kQmFzZU1pbnRzW2ldLCBjcmVhdG9yKTtcbiAgICAgIGNvbnN0IHVzZXJDb25kUXVvdGVBdGEgPSBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyhjb25kUXVvdGVNaW50c1tpXSwgY3JlYXRvcik7XG5cbiAgICAgIGluc3RydWN0aW9ucy5wdXNoKFxuICAgICAgICBjcmVhdGVBc3NvY2lhdGVkVG9rZW5BY2NvdW50SWRlbXBvdGVudEluc3RydWN0aW9uKFxuICAgICAgICAgIGNyZWF0b3IsXG4gICAgICAgICAgdXNlckNvbmRCYXNlQXRhLFxuICAgICAgICAgIGNyZWF0b3IsXG4gICAgICAgICAgY29uZEJhc2VNaW50c1tpXVxuICAgICAgICApLFxuICAgICAgICBjcmVhdGVBc3NvY2lhdGVkVG9rZW5BY2NvdW50SWRlbXBvdGVudEluc3RydWN0aW9uKFxuICAgICAgICAgIGNyZWF0b3IsXG4gICAgICAgICAgdXNlckNvbmRRdW90ZUF0YSxcbiAgICAgICAgICBjcmVhdG9yLFxuICAgICAgICAgIGNvbmRRdW90ZU1pbnRzW2ldXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gU2VuZCB0cmFuc2FjdGlvblxuICAgIGNvbnN0IHR4ID0gbmV3IFRyYW5zYWN0aW9uKCkuYWRkKC4uLmluc3RydWN0aW9ucyk7XG4gICAgcmV0dXJuIHByb3ZpZGVyLnNlbmRBbmRDb25maXJtKHR4KTtcbiAgfVxuXG4gIGFzeW5jIGZpbmFsaXplUHJvcG9zYWwoc2lnbmVyOiBQdWJsaWNLZXksIHByb3Bvc2FsUGRhOiBQdWJsaWNLZXksIG9wdGlvbnM/OiBUeE9wdGlvbnMpIHtcbiAgICBjb25zdCBwcm9wb3NhbCA9IGF3YWl0IHRoaXMuZmV0Y2hQcm9wb3NhbChwcm9wb3NhbFBkYSk7XG4gICAgY29uc3QgdmF1bHQgPSBhd2FpdCB0aGlzLnZhdWx0LmZldGNoVmF1bHQocHJvcG9zYWwudmF1bHQpO1xuICAgIGNvbnN0IG51bU9wdGlvbnMgPSBwcm9wb3NhbC5udW1PcHRpb25zO1xuXG4gICAgLy8gQnVpbGQgcmVtYWluaW5nIGFjY291bnRzICgzIHBlciBwb29sOiBwb29sLCByZXNlcnZlX2EsIHJlc2VydmVfYilcbiAgICBjb25zdCByZW1haW5pbmdBY2NvdW50czogeyBwdWJrZXk6IFB1YmxpY0tleTsgaXNTaWduZXI6IGJvb2xlYW47IGlzV3JpdGFibGU6IGJvb2xlYW4gfVtdID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bU9wdGlvbnM7IGkrKykge1xuICAgICAgY29uc3QgcG9vbCA9IHByb3Bvc2FsLnBvb2xzW2ldO1xuICAgICAgY29uc3QgW3Jlc2VydmVBXSA9IGRlcml2ZVJlc2VydmVQREEocG9vbCwgdmF1bHQuY29uZFF1b3RlTWludHNbaV0sIHRoaXMuYW1tLnByb2dyYW1JZCk7XG4gICAgICBjb25zdCBbcmVzZXJ2ZUJdID0gZGVyaXZlUmVzZXJ2ZVBEQShwb29sLCB2YXVsdC5jb25kQmFzZU1pbnRzW2ldLCB0aGlzLmFtbS5wcm9ncmFtSWQpO1xuXG4gICAgICByZW1haW5pbmdBY2NvdW50cy5wdXNoKHsgcHVia2V5OiBwb29sLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSk7XG4gICAgICByZW1haW5pbmdBY2NvdW50cy5wdXNoKHsgcHVia2V5OiByZXNlcnZlQSwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiBmYWxzZSB9KTtcbiAgICAgIHJlbWFpbmluZ0FjY291bnRzLnB1c2goeyBwdWJrZXk6IHJlc2VydmVCLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IGZhbHNlIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGJ1aWxkZXIgPSBmaW5hbGl6ZVByb3Bvc2FsKFxuICAgICAgdGhpcy5wcm9ncmFtLFxuICAgICAgc2lnbmVyLFxuICAgICAgcHJvcG9zYWxQZGEsXG4gICAgICBwcm9wb3NhbC52YXVsdCxcbiAgICAgIHJlbWFpbmluZ0FjY291bnRzXG4gICAgKS5wcmVJbnN0cnVjdGlvbnModGhpcy5tYXliZUFkZENvbXB1dGVCdWRnZXQob3B0aW9ucykpO1xuXG4gICAgcmV0dXJuIHsgYnVpbGRlciB9O1xuICB9XG5cbiAgYXN5bmMgcmVkZWVtTGlxdWlkaXR5KGNyZWF0b3I6IFB1YmxpY0tleSwgcHJvcG9zYWxQZGE6IFB1YmxpY0tleSwgb3B0aW9ucz86IFR4T3B0aW9ucykge1xuICAgIGNvbnN0IHByb3Bvc2FsID0gYXdhaXQgdGhpcy5mZXRjaFByb3Bvc2FsKHByb3Bvc2FsUGRhKTtcbiAgICBjb25zdCB2YXVsdCA9IGF3YWl0IHRoaXMudmF1bHQuZmV0Y2hWYXVsdChwcm9wb3NhbC52YXVsdCk7XG4gICAgY29uc3QgbnVtT3B0aW9ucyA9IHByb3Bvc2FsLm51bU9wdGlvbnM7XG5cbiAgICBjb25zdCB7IHdpbm5pbmdJZHggfSA9IHBhcnNlUHJvcG9zYWxTdGF0ZShwcm9wb3NhbC5zdGF0ZSk7XG4gICAgaWYgKHdpbm5pbmdJZHggPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlByb3Bvc2FsIG5vdCBmaW5hbGl6ZWRcIik7XG4gICAgfVxuICAgIGNvbnN0IHdpbm5pbmdQb29sID0gcHJvcG9zYWwucG9vbHNbd2lubmluZ0lkeF07XG5cbiAgICAvLyBEZXJpdmUgd2lubmluZyBwb29sIHJlc2VydmVzXG4gICAgY29uc3QgW3Jlc2VydmVBXSA9IGRlcml2ZVJlc2VydmVQREEod2lubmluZ1Bvb2wsIHZhdWx0LmNvbmRRdW90ZU1pbnRzW3dpbm5pbmdJZHhdLCB0aGlzLmFtbS5wcm9ncmFtSWQpO1xuICAgIGNvbnN0IFtyZXNlcnZlQl0gPSBkZXJpdmVSZXNlcnZlUERBKHdpbm5pbmdQb29sLCB2YXVsdC5jb25kQmFzZU1pbnRzW3dpbm5pbmdJZHhdLCB0aGlzLmFtbS5wcm9ncmFtSWQpO1xuXG4gICAgLy8gVXNlcidzIHdpbm5pbmcgY29uZGl0aW9uYWwgdG9rZW4gQVRBc1xuICAgIGNvbnN0IGNyZWF0b3JDb25kUXVvdGVBdGEgPSBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh2YXVsdC5jb25kUXVvdGVNaW50c1t3aW5uaW5nSWR4XSwgY3JlYXRvcik7XG4gICAgY29uc3QgY3JlYXRvckNvbmRCYXNlQXRhID0gZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmModmF1bHQuY29uZEJhc2VNaW50c1t3aW5uaW5nSWR4XSwgY3JlYXRvcik7XG5cbiAgICAvLyBCdWlsZCByZW1haW5pbmcgYWNjb3VudHMgKHNlZSByZWRlZW1fbGlxdWlkaXR5LnJzKVxuICAgIGNvbnN0IHJlbWFpbmluZ0FjY291bnRzOiB7IHB1YmtleTogUHVibGljS2V5OyBpc1NpZ25lcjogYm9vbGVhbjsgaXNXcml0YWJsZTogYm9vbGVhbiB9W10gPSBbXG4gICAgICAvLyByZW1vdmVfbGlxdWlkaXR5IGFjY291bnRzICgwLTMpXG4gICAgICB7IHB1YmtleTogcmVzZXJ2ZUEsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LFxuICAgICAgeyBwdWJrZXk6IHJlc2VydmVCLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSxcbiAgICAgIHsgcHVia2V5OiBjcmVhdG9yQ29uZFF1b3RlQXRhLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSxcbiAgICAgIHsgcHVia2V5OiBjcmVhdG9yQ29uZEJhc2VBdGEsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LFxuXG4gICAgICAvLyByZWRlZW1fd2lubmluZ3MgYmFzZSBmaXhlZCBhY2NvdW50cyAoNC02KVxuICAgICAgeyBwdWJrZXk6IHZhdWx0LmJhc2VNaW50LmFkZHJlc3MsIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogZmFsc2UgfSxcbiAgICAgIHsgcHVia2V5OiBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh2YXVsdC5iYXNlTWludC5hZGRyZXNzLCBwcm9wb3NhbC52YXVsdCwgdHJ1ZSksIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9LFxuICAgICAgeyBwdWJrZXk6IGdldEFzc29jaWF0ZWRUb2tlbkFkZHJlc3NTeW5jKHZhdWx0LmJhc2VNaW50LmFkZHJlc3MsIGNyZWF0b3IpLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSxcbiAgICBdO1xuXG4gICAgLy8gcmVkZWVtX3dpbm5pbmdzIGJhc2UgcmVtYWluaW5nICg3Li43KzJOKTogW2NvbmRfYmFzZV9taW50X2ksIHVzZXJfY29uZF9iYXNlX2F0YV9pXVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtT3B0aW9uczsgaSsrKSB7XG4gICAgICByZW1haW5pbmdBY2NvdW50cy5wdXNoKHsgcHVia2V5OiB2YXVsdC5jb25kQmFzZU1pbnRzW2ldLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSk7XG4gICAgICByZW1haW5pbmdBY2NvdW50cy5wdXNoKHsgcHVia2V5OiBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh2YXVsdC5jb25kQmFzZU1pbnRzW2ldLCBjcmVhdG9yKSwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0pO1xuICAgIH1cblxuICAgIC8vIHJlZGVlbV93aW5uaW5ncyBxdW90ZSBmaXhlZCBhY2NvdW50c1xuICAgIHJlbWFpbmluZ0FjY291bnRzLnB1c2goeyBwdWJrZXk6IHZhdWx0LnF1b3RlTWludC5hZGRyZXNzLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IGZhbHNlIH0pO1xuICAgIHJlbWFpbmluZ0FjY291bnRzLnB1c2goeyBwdWJrZXk6IGdldEFzc29jaWF0ZWRUb2tlbkFkZHJlc3NTeW5jKHZhdWx0LnF1b3RlTWludC5hZGRyZXNzLCBwcm9wb3NhbC52YXVsdCwgdHJ1ZSksIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9KTtcbiAgICByZW1haW5pbmdBY2NvdW50cy5wdXNoKHsgcHVia2V5OiBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh2YXVsdC5xdW90ZU1pbnQuYWRkcmVzcywgY3JlYXRvciksIGlzU2lnbmVyOiBmYWxzZSwgaXNXcml0YWJsZTogdHJ1ZSB9KTtcblxuICAgIC8vIHJlZGVlbV93aW5uaW5ncyBxdW90ZSByZW1haW5pbmc6IFtjb25kX3F1b3RlX21pbnRfaSwgdXNlcl9jb25kX3F1b3RlX2F0YV9pXVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtT3B0aW9uczsgaSsrKSB7XG4gICAgICByZW1haW5pbmdBY2NvdW50cy5wdXNoKHsgcHVia2V5OiB2YXVsdC5jb25kUXVvdGVNaW50c1tpXSwgaXNTaWduZXI6IGZhbHNlLCBpc1dyaXRhYmxlOiB0cnVlIH0pO1xuICAgICAgcmVtYWluaW5nQWNjb3VudHMucHVzaCh7IHB1YmtleTogZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmModmF1bHQuY29uZFF1b3RlTWludHNbaV0sIGNyZWF0b3IpLCBpc1NpZ25lcjogZmFsc2UsIGlzV3JpdGFibGU6IHRydWUgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgYnVpbGRlciA9IHJlZGVlbUxpcXVpZGl0eShcbiAgICAgIHRoaXMucHJvZ3JhbSxcbiAgICAgIGNyZWF0b3IsXG4gICAgICBwcm9wb3NhbFBkYSxcbiAgICAgIHByb3Bvc2FsLnZhdWx0LFxuICAgICAgd2lubmluZ1Bvb2wsXG4gICAgICByZW1haW5pbmdBY2NvdW50c1xuICAgICkucHJlSW5zdHJ1Y3Rpb25zKHRoaXMubWF5YmVBZGRDb21wdXRlQnVkZ2V0KG9wdGlvbnMpKTtcblxuICAgIHJldHVybiB7IGJ1aWxkZXIsIG51bU9wdGlvbnMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIEFkZHJlc3MgTG9va3VwIFRhYmxlIGZvciByZWRlbXB0aW9uIG9wZXJhdGlvbnMuXG4gICAqIFJlcXVpcmVkIGZvciBwcm9wb3NhbHMgd2l0aCAzKyBvcHRpb25zIHRvIGF2b2lkIGV4Y2VlZGluZyB0cmFuc2FjdGlvbiBzaXplIGxpbWl0cy5cbiAgICpcbiAgICogQHBhcmFtIGNyZWF0b3IgLSBUaGUgdXNlciByZWRlZW1pbmcgKGNyZWF0b3Igb2YgcHJvcG9zYWwgb3IgbGlxdWlkaXR5IHByb3ZpZGVyKVxuICAgKiBAcGFyYW0gcHJvcG9zYWxQZGEgLSBUaGUgcHJvcG9zYWwgUERBXG4gICAqIEByZXR1cm5zIEFMVCBhZGRyZXNzXG4gICAqL1xuICBhc3luYyBjcmVhdGVSZWRlbXB0aW9uQUxUKFxuICAgIGNyZWF0b3I6IFB1YmxpY0tleSxcbiAgICBwcm9wb3NhbFBkYTogUHVibGljS2V5LFxuICApOiBQcm9taXNlPHsgYWx0QWRkcmVzczogUHVibGljS2V5IH0+IHtcbiAgICBjb25zdCBwcm92aWRlciA9IHRoaXMucHJvZ3JhbS5wcm92aWRlciBhcyBBbmNob3JQcm92aWRlcjtcbiAgICBjb25zdCBwcm9wb3NhbCA9IGF3YWl0IHRoaXMuZmV0Y2hQcm9wb3NhbChwcm9wb3NhbFBkYSk7XG4gICAgY29uc3QgdmF1bHQgPSBhd2FpdCB0aGlzLnZhdWx0LmZldGNoVmF1bHQocHJvcG9zYWwudmF1bHQpO1xuICAgIGNvbnN0IG51bU9wdGlvbnMgPSBwcm9wb3NhbC5udW1PcHRpb25zO1xuXG4gICAgY29uc3QgeyB3aW5uaW5nSWR4IH0gPSBwYXJzZVByb3Bvc2FsU3RhdGUocHJvcG9zYWwuc3RhdGUpO1xuICAgIGlmICh3aW5uaW5nSWR4ID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQcm9wb3NhbCBub3QgZmluYWxpemVkXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGFkZHJlc3NlczogUHVibGljS2V5W10gPSBbXG4gICAgICAvLyBQcm9ncmFtc1xuICAgICAgdGhpcy5wcm9ncmFtSWQsXG4gICAgICB0aGlzLnZhdWx0LnByb2dyYW1JZCxcbiAgICAgIHRoaXMuYW1tLnByb2dyYW1JZCxcbiAgICAgIFN5c3RlbVByb2dyYW0ucHJvZ3JhbUlkLFxuICAgICAgVE9LRU5fUFJPR1JBTV9JRCxcbiAgICAgIEFTU09DSUFURURfVE9LRU5fUFJPR1JBTV9JRCxcbiAgICAgIC8vIENvcmUgYWNjb3VudHNcbiAgICAgIHByb3Bvc2FsUGRhLFxuICAgICAgcHJvcG9zYWwudmF1bHQsXG4gICAgICBwcm9wb3NhbC5tb2RlcmF0b3IsXG4gICAgICB2YXVsdC5iYXNlTWludC5hZGRyZXNzLFxuICAgICAgdmF1bHQucXVvdGVNaW50LmFkZHJlc3MsXG4gICAgICAvLyBXaW5uaW5nIHBvb2wgYW5kIHJlc2VydmVzXG4gICAgICBwcm9wb3NhbC5wb29sc1t3aW5uaW5nSWR4XSxcbiAgICAgIC8vIFZhdWx0IHRva2VuIGFjY291bnRzXG4gICAgICBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh2YXVsdC5iYXNlTWludC5hZGRyZXNzLCBwcm9wb3NhbC52YXVsdCwgdHJ1ZSksXG4gICAgICBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh2YXVsdC5xdW90ZU1pbnQuYWRkcmVzcywgcHJvcG9zYWwudmF1bHQsIHRydWUpLFxuICAgICAgLy8gQ3JlYXRvcidzIGJhc2UvcXVvdGUgQVRBc1xuICAgICAgZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmModmF1bHQuYmFzZU1pbnQuYWRkcmVzcywgY3JlYXRvciksXG4gICAgICBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh2YXVsdC5xdW90ZU1pbnQuYWRkcmVzcywgY3JlYXRvciksXG4gICAgXTtcblxuICAgIC8vIFdpbm5pbmcgcG9vbCByZXNlcnZlc1xuICAgIGNvbnN0IFtyZXNlcnZlQV0gPSBkZXJpdmVSZXNlcnZlUERBKHByb3Bvc2FsLnBvb2xzW3dpbm5pbmdJZHhdLCB2YXVsdC5jb25kUXVvdGVNaW50c1t3aW5uaW5nSWR4XSwgdGhpcy5hbW0ucHJvZ3JhbUlkKTtcbiAgICBjb25zdCBbcmVzZXJ2ZUJdID0gZGVyaXZlUmVzZXJ2ZVBEQShwcm9wb3NhbC5wb29sc1t3aW5uaW5nSWR4XSwgdmF1bHQuY29uZEJhc2VNaW50c1t3aW5uaW5nSWR4XSwgdGhpcy5hbW0ucHJvZ3JhbUlkKTtcbiAgICBhZGRyZXNzZXMucHVzaChyZXNlcnZlQSwgcmVzZXJ2ZUIpO1xuXG4gICAgLy8gUGVyLW9wdGlvbiBhY2NvdW50cyAoY29uZGl0aW9uYWwgbWludHMgYW5kIHVzZXIgQVRBcylcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bU9wdGlvbnM7IGkrKykge1xuICAgICAgYWRkcmVzc2VzLnB1c2goXG4gICAgICAgIHZhdWx0LmNvbmRCYXNlTWludHNbaV0sXG4gICAgICAgIHZhdWx0LmNvbmRRdW90ZU1pbnRzW2ldLFxuICAgICAgICBnZXRBc3NvY2lhdGVkVG9rZW5BZGRyZXNzU3luYyh2YXVsdC5jb25kQmFzZU1pbnRzW2ldLCBjcmVhdG9yKSxcbiAgICAgICAgZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmModmF1bHQuY29uZFF1b3RlTWludHNbaV0sIGNyZWF0b3IpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBHZXQgcmVjZW50IHNsb3QgZm9yIEFMVCBjcmVhdGlvblxuICAgIGNvbnN0IHNsb3QgPSBhd2FpdCBwcm92aWRlci5jb25uZWN0aW9uLmdldFNsb3QoXCJmaW5hbGl6ZWRcIik7XG5cbiAgICBjb25zdCBbY3JlYXRlSXgsIGFsdEFkZHJlc3NdID0gQWRkcmVzc0xvb2t1cFRhYmxlUHJvZ3JhbS5jcmVhdGVMb29rdXBUYWJsZSh7XG4gICAgICBhdXRob3JpdHk6IGNyZWF0b3IsXG4gICAgICBwYXllcjogY3JlYXRvcixcbiAgICAgIHJlY2VudFNsb3Q6IHNsb3QsXG4gICAgfSk7XG5cbiAgICAvLyBDcmVhdGUgQUxUXG4gICAgY29uc3QgY3JlYXRlVHggPSBuZXcgVHJhbnNhY3Rpb24oKS5hZGQoY3JlYXRlSXgpO1xuICAgIGNvbnN0IHsgYmxvY2toYXNoOiBjcmVhdGVCbG9ja2hhc2gsIGxhc3RWYWxpZEJsb2NrSGVpZ2h0OiBjcmVhdGVMYXN0VmFsaWRCbG9ja0hlaWdodCB9ID1cbiAgICAgIGF3YWl0IHByb3ZpZGVyLmNvbm5lY3Rpb24uZ2V0TGF0ZXN0QmxvY2toYXNoKCdjb25maXJtZWQnKTtcbiAgICBjcmVhdGVUeC5yZWNlbnRCbG9ja2hhc2ggPSBjcmVhdGVCbG9ja2hhc2g7XG4gICAgY3JlYXRlVHguZmVlUGF5ZXIgPSBjcmVhdG9yO1xuICAgIGNvbnN0IHNpZ25lZFR4ID0gYXdhaXQgcHJvdmlkZXIud2FsbGV0LnNpZ25UcmFuc2FjdGlvbihjcmVhdGVUeCk7XG4gICAgY29uc3Qgc2lnID0gYXdhaXQgcHJvdmlkZXIuY29ubmVjdGlvbi5zZW5kUmF3VHJhbnNhY3Rpb24oc2lnbmVkVHguc2VyaWFsaXplKCksIHtcbiAgICAgIHNraXBQcmVmbGlnaHQ6IHRydWUsXG4gICAgfSk7XG4gICAgYXdhaXQgcHJvdmlkZXIuY29ubmVjdGlvbi5jb25maXJtVHJhbnNhY3Rpb24oe1xuICAgICAgc2lnbmF0dXJlOiBzaWcsXG4gICAgICBibG9ja2hhc2g6IGNyZWF0ZUJsb2NraGFzaCxcbiAgICAgIGxhc3RWYWxpZEJsb2NrSGVpZ2h0OiBjcmVhdGVMYXN0VmFsaWRCbG9ja0hlaWdodCxcbiAgICB9LCBcImNvbmZpcm1lZFwiKTtcblxuICAgIC8vIEV4dGVuZCBBTFQgd2l0aCBhZGRyZXNzZXNcbiAgICAvLyBVc2Ugc2tpcFByZWZsaWdodCB0byBhdm9pZCByYWNlIGNvbmRpdGlvbiB3aGVyZSBzaW11bGF0aW9uIHNlZXMgc3RhbGUgc3RhdGVcbiAgICAvLyBiZWZvcmUgcHJldmlvdXMgZXh0ZW5kIGhhcyBwcm9wYWdhdGVkIChzYW1lIHBhdHRlcm4gYXMgQ1JFQVRFIGFib3ZlKVxuICAgIGNvbnN0IENIVU5LX1NJWkUgPSAyMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFkZHJlc3Nlcy5sZW5ndGg7IGkgKz0gQ0hVTktfU0laRSkge1xuICAgICAgY29uc3QgY2h1bmsgPSBhZGRyZXNzZXMuc2xpY2UoaSwgaSArIENIVU5LX1NJWkUpO1xuICAgICAgY29uc3QgZXh0ZW5kSXggPSBBZGRyZXNzTG9va3VwVGFibGVQcm9ncmFtLmV4dGVuZExvb2t1cFRhYmxlKHtcbiAgICAgICAgcGF5ZXI6IGNyZWF0b3IsXG4gICAgICAgIGF1dGhvcml0eTogY3JlYXRvcixcbiAgICAgICAgbG9va3VwVGFibGU6IGFsdEFkZHJlc3MsXG4gICAgICAgIGFkZHJlc3NlczogY2h1bmssXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGV4dGVuZFR4ID0gbmV3IFRyYW5zYWN0aW9uKCkuYWRkKGV4dGVuZEl4KTtcbiAgICAgIGNvbnN0IHsgYmxvY2toYXNoOiBleHRlbmRCbG9ja2hhc2gsIGxhc3RWYWxpZEJsb2NrSGVpZ2h0OiBleHRlbmRMYXN0VmFsaWRCbG9ja0hlaWdodCB9ID1cbiAgICAgICAgYXdhaXQgcHJvdmlkZXIuY29ubmVjdGlvbi5nZXRMYXRlc3RCbG9ja2hhc2goJ2NvbmZpcm1lZCcpO1xuICAgICAgZXh0ZW5kVHgucmVjZW50QmxvY2toYXNoID0gZXh0ZW5kQmxvY2toYXNoO1xuICAgICAgZXh0ZW5kVHguZmVlUGF5ZXIgPSBjcmVhdG9yO1xuICAgICAgY29uc3Qgc2lnbmVkRXh0ZW5kVHggPSBhd2FpdCBwcm92aWRlci53YWxsZXQuc2lnblRyYW5zYWN0aW9uKGV4dGVuZFR4KTtcbiAgICAgIGNvbnN0IGV4dGVuZFNpZyA9IGF3YWl0IHByb3ZpZGVyLmNvbm5lY3Rpb24uc2VuZFJhd1RyYW5zYWN0aW9uKHNpZ25lZEV4dGVuZFR4LnNlcmlhbGl6ZSgpLCB7XG4gICAgICAgIHNraXBQcmVmbGlnaHQ6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHByb3ZpZGVyLmNvbm5lY3Rpb24uY29uZmlybVRyYW5zYWN0aW9uKHtcbiAgICAgICAgc2lnbmF0dXJlOiBleHRlbmRTaWcsXG4gICAgICAgIGJsb2NraGFzaDogZXh0ZW5kQmxvY2toYXNoLFxuICAgICAgICBsYXN0VmFsaWRCbG9ja0hlaWdodDogZXh0ZW5kTGFzdFZhbGlkQmxvY2tIZWlnaHQsXG4gICAgICB9LCBcImNvbmZpcm1lZFwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBhbHRBZGRyZXNzIH07XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGEgdmVyc2lvbmVkIHRyYW5zYWN0aW9uIGZvciByZWRlZW1pbmcgbGlxdWlkaXR5IHdpdGggQUxULlxuICAgKiBSZXF1aXJlZCBmb3IgcHJvcG9zYWxzIHdpdGggMysgb3B0aW9ucyB0byBhdm9pZCBleGNlZWRpbmcgdHJhbnNhY3Rpb24gc2l6ZSBsaW1pdHMuXG4gICAqXG4gICAqIEBwYXJhbSBjcmVhdG9yIC0gVGhlIHVzZXIgcmVkZWVtaW5nXG4gICAqIEBwYXJhbSBwcm9wb3NhbFBkYSAtIFRoZSBwcm9wb3NhbCBQREFcbiAgICogQHBhcmFtIGFsdEFkZHJlc3MgLSBPcHRpb25hbCBBTFQgYWRkcmVzcyAod2lsbCBiZSBjcmVhdGVkIGlmIG5vdCBwcm92aWRlZCBmb3IgMysgb3B0aW9ucylcbiAgICogQHJldHVybnMgVW5zaWduZWQgdmVyc2lvbmVkIHRyYW5zYWN0aW9uLCBBTFQgYWRkcmVzcywgbnVtYmVyIG9mIG9wdGlvbnMsIGFuZCBibG9ja2hhc2ggaW5mbyBmb3IgY29uZmlybWF0aW9uXG4gICAqL1xuICBhc3luYyByZWRlZW1MaXF1aWRpdHlWZXJzaW9uZWQoXG4gICAgY3JlYXRvcjogUHVibGljS2V5LFxuICAgIHByb3Bvc2FsUGRhOiBQdWJsaWNLZXksXG4gICAgYWx0QWRkcmVzcz86IFB1YmxpY0tleSxcbiAgKTogUHJvbWlzZTx7XG4gICAgdmVyc2lvbmVkVHg6IFZlcnNpb25lZFRyYW5zYWN0aW9uO1xuICAgIGFsdEFkZHJlc3M6IFB1YmxpY0tleTtcbiAgICBudW1PcHRpb25zOiBudW1iZXI7XG4gICAgYmxvY2toYXNoOiBzdHJpbmc7XG4gICAgbGFzdFZhbGlkQmxvY2tIZWlnaHQ6IG51bWJlcjtcbiAgfT4ge1xuICAgIGNvbnN0IHByb3ZpZGVyID0gdGhpcy5wcm9ncmFtLnByb3ZpZGVyIGFzIEFuY2hvclByb3ZpZGVyO1xuICAgIGNvbnN0IHsgYnVpbGRlciwgbnVtT3B0aW9ucyB9ID0gYXdhaXQgdGhpcy5yZWRlZW1MaXF1aWRpdHkoY3JlYXRvciwgcHJvcG9zYWxQZGEpO1xuXG4gICAgLy8gQ3JlYXRlIEFMVCBpZiBub3QgcHJvdmlkZWQgYW5kIG5lZWRlZFxuICAgIGxldCBhbHRQdWJrZXkgPSBhbHRBZGRyZXNzO1xuICAgIGxldCB2ZXJpZmllZEFMVDogQWRkcmVzc0xvb2t1cFRhYmxlQWNjb3VudCB8IG51bGwgPSBudWxsO1xuXG4gICAgaWYgKCFhbHRQdWJrZXkgJiYgbnVtT3B0aW9ucyA+PSAzKSB7XG4gICAgICBjb25zb2xlLmxvZyhgICBDcmVhdGluZyByZWRlbXB0aW9uIEFMVCBmb3IgJHtudW1PcHRpb25zfSBvcHRpb25zLi4uYCk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmNyZWF0ZVJlZGVtcHRpb25BTFQoY3JlYXRvciwgcHJvcG9zYWxQZGEpO1xuICAgICAgYWx0UHVia2V5ID0gcmVzdWx0LmFsdEFkZHJlc3M7XG4gICAgICBjb25zb2xlLmxvZyhgICDinJMgUmVkZW1wdGlvbiBBTFQgY3JlYXRlZDogJHthbHRQdWJrZXkudG9CYXNlNTgoKX1gKTtcblxuICAgICAgLy8gV2FpdCBmb3IgQUxUIHRvIGJlIGZ1bGx5IGF2YWlsYWJsZSB3aXRoIGFsbCBhZGRyZXNzZXNcbiAgICAgIC8vIFVzZSBsb25nZXIgZGVsYXlzIGFmdGVyIGV4dGVuZGluZyB0byBlbnN1cmUgcHJvcGFnYXRpb25cbiAgICAgIGNvbnNvbGUubG9nKGAgIFdhaXRpbmcgZm9yIEFMVCBwcm9wYWdhdGlvbi4uLmApO1xuICAgICAgY29uc3QgZXhwZWN0ZWRBZGRyZXNzZXMgPSAxOCArIChudW1PcHRpb25zICogNCk7IC8vIEJhc2UgYWNjb3VudHMgKyBwZXItb3B0aW9uIGFjY291bnRzXG4gICAgICBsZXQgYXR0ZW1wdHMgPSAwO1xuXG4gICAgICAvLyBJbml0aWFsIGRlbGF5IGFmdGVyIGV4dGVuc2lvblxuICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDIwMDApKTtcblxuICAgICAgd2hpbGUgKGF0dGVtcHRzIDwgMzApIHtcbiAgICAgICAgY29uc3QgYWx0QWNjb3VudCA9IGF3YWl0IHByb3ZpZGVyLmNvbm5lY3Rpb24uZ2V0QWRkcmVzc0xvb2t1cFRhYmxlKGFsdFB1YmtleSwge1xuICAgICAgICAgIGNvbW1pdG1lbnQ6ICdjb25maXJtZWQnLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGFsdEFjY291bnQudmFsdWUpIHtcbiAgICAgICAgICBjb25zdCBhZGRyZXNzQ291bnQgPSBhbHRBY2NvdW50LnZhbHVlLnN0YXRlLmFkZHJlc3Nlcy5sZW5ndGg7XG4gICAgICAgICAgY29uc29sZS5sb2coYCAgQXR0ZW1wdCAke2F0dGVtcHRzICsgMX06IEFMVCBoYXMgJHthZGRyZXNzQ291bnR9LyR7ZXhwZWN0ZWRBZGRyZXNzZXN9IGFkZHJlc3Nlc2ApO1xuICAgICAgICAgIGlmIChhZGRyZXNzQ291bnQgPj0gZXhwZWN0ZWRBZGRyZXNzZXMpIHtcbiAgICAgICAgICAgIHZlcmlmaWVkQUxUID0gYWx0QWNjb3VudC52YWx1ZTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGAgIOKckyBBTFQgdmVyaWZpZWQgd2l0aCAke2FkZHJlc3NDb3VudH0gYWRkcmVzc2VzYCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMDApKTtcbiAgICAgICAgYXR0ZW1wdHMrKztcbiAgICAgIH1cblxuICAgICAgaWYgKCF2ZXJpZmllZEFMVCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFMVCBmYWlsZWQgdG8gcG9wdWxhdGUgd2l0aCBleHBlY3RlZCAke2V4cGVjdGVkQWRkcmVzc2VzfSBhZGRyZXNzZXMgYWZ0ZXIgJHthdHRlbXB0c30gYXR0ZW1wdHNgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWFsdFB1YmtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQUxUIGFkZHJlc3MgcmVxdWlyZWQgZm9yIG11bHRpLW9wdGlvbiByZWRlbXB0aW9uXCIpO1xuICAgIH1cblxuICAgIC8vIEZldGNoIEFMVCBpZiB3ZSBkb24ndCBoYXZlIGl0IHZlcmlmaWVkIGFscmVhZHlcbiAgICBpZiAoIXZlcmlmaWVkQUxUKSB7XG4gICAgICB2ZXJpZmllZEFMVCA9IGF3YWl0IHRoaXMuZmV0Y2hBTFQoYWx0UHVia2V5KTtcbiAgICB9XG5cbiAgICAvLyBCdWlsZCBpbnN0cnVjdGlvblxuICAgIGNvbnN0IGluc3RydWN0aW9uID0gYXdhaXQgYnVpbGRlci5pbnN0cnVjdGlvbigpO1xuICAgIGNvbnN0IGNvbXB1dGVCdWRnZXRJeCA9IENvbXB1dGVCdWRnZXRQcm9ncmFtLnNldENvbXB1dGVVbml0TGltaXQoeyB1bml0czogNTAwXzAwMCB9KTtcblxuICAgIC8vIEdldCBmcmVzaCBibG9ja2hhc2ggd2l0aCBsYXN0VmFsaWRCbG9ja0hlaWdodCBmb3IgY29uZmlybWF0aW9uIHRyYWNraW5nXG4gICAgY29uc3QgeyBibG9ja2hhc2gsIGxhc3RWYWxpZEJsb2NrSGVpZ2h0IH0gPSBhd2FpdCBwcm92aWRlci5jb25uZWN0aW9uLmdldExhdGVzdEJsb2NraGFzaCgnY29uZmlybWVkJyk7XG5cbiAgICAvLyBCdWlsZCB2ZXJzaW9uZWQgdHJhbnNhY3Rpb24gdXNpbmcgdGhlIHZlcmlmaWVkIEFMVCAobm8gcmUtZmV0Y2gpXG4gICAgY29uc3QgdmVyc2lvbmVkVHggPSB0aGlzLmJ1aWxkVmVyc2lvbmVkVHhXaXRoQUxUKFxuICAgICAgY3JlYXRvcixcbiAgICAgIFtjb21wdXRlQnVkZ2V0SXgsIGluc3RydWN0aW9uXSxcbiAgICAgIHZlcmlmaWVkQUxULFxuICAgICAgYmxvY2toYXNoLFxuICAgICk7XG5cbiAgICAvLyBSZXR1cm4gdGhlIHZlcnNpb25lZCB0cmFuc2FjdGlvbiBhbG9uZyB3aXRoIGJsb2NraGFzaCBpbmZvIGZvciBwcm9wZXIgY29uZmlybWF0aW9uXG4gICAgLy8gVGhpcyBhbGxvd3MgdGhlIGNhbGxlciB0byB1c2UgdGhlaXIgb3duIHNpZ25pbmcgbWVjaGFuaXNtIChlLmcuLCBrZXlwYWlyLnNpZ24pXG4gICAgcmV0dXJuIHsgdmVyc2lvbmVkVHgsIGFsdEFkZHJlc3M6IGFsdFB1YmtleSwgbnVtT3B0aW9ucywgYmxvY2toYXNoLCBsYXN0VmFsaWRCbG9ja0hlaWdodCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEhlbHBlciB0byBzZW5kIGEgc2lnbmVkIHZlcnNpb25lZCB0cmFuc2FjdGlvbiB3aXRoIHJvYnVzdCBjb25maXJtYXRpb24gaGFuZGxpbmcuXG4gICAqIFVzZXMgYmxvY2toYXNoLWJhc2VkIGNvbmZpcm1hdGlvbiB0byBwcm9wZXJseSBkZXRlY3QgdHJhbnNhY3Rpb24gZXhwaXJhdGlvblxuICAgKiBpbnN0ZWFkIG9mIHJlbHlpbmcgb24gYSBmaXhlZCB0aW1lb3V0LlxuICAgKlxuICAgKiBAcGFyYW0gc2lnbmVkVHggLSBUaGUgc2lnbmVkIHZlcnNpb25lZCB0cmFuc2FjdGlvbiB0byBzZW5kXG4gICAqIEBwYXJhbSBjb25maXJtYXRpb25JbmZvIC0gT3B0aW9uYWwgYmxvY2toYXNoIGluZm8gZnJvbSB3aGVuIHRoZSB0cmFuc2FjdGlvbiB3YXMgYnVpbHQuXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICBJZiBub3QgcHJvdmlkZWQsIGEgZnJlc2ggYmxvY2toYXNoIHdpbGwgYmUgZmV0Y2hlZCAobGVzcyBhY2N1cmF0ZSkuXG4gICAqL1xuICBhc3luYyBzZW5kVmVyc2lvbmVkVHJhbnNhY3Rpb24oXG4gICAgc2lnbmVkVHg6IFZlcnNpb25lZFRyYW5zYWN0aW9uLFxuICAgIGNvbmZpcm1hdGlvbkluZm8/OiB7IGJsb2NraGFzaDogc3RyaW5nOyBsYXN0VmFsaWRCbG9ja0hlaWdodDogbnVtYmVyIH0sXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgcHJvdmlkZXIgPSB0aGlzLnByb2dyYW0ucHJvdmlkZXIgYXMgQW5jaG9yUHJvdmlkZXI7XG5cbiAgICAvLyBVc2UgcHJvdmlkZWQgYmxvY2toYXNoIGluZm8gb3IgZmV0Y2ggZnJlc2ggb25lXG4gICAgLy8gVXNpbmcgdGhlIG9yaWdpbmFsIGJsb2NraGFzaCBpcyBtb3JlIGFjY3VyYXRlIGZvciBkZXRlY3RpbmcgZXhwaXJhdGlvblxuICAgIGxldCBibG9ja2hhc2g6IHN0cmluZztcbiAgICBsZXQgbGFzdFZhbGlkQmxvY2tIZWlnaHQ6IG51bWJlcjtcblxuICAgIGlmIChjb25maXJtYXRpb25JbmZvKSB7XG4gICAgICBibG9ja2hhc2ggPSBjb25maXJtYXRpb25JbmZvLmJsb2NraGFzaDtcbiAgICAgIGxhc3RWYWxpZEJsb2NrSGVpZ2h0ID0gY29uZmlybWF0aW9uSW5mby5sYXN0VmFsaWRCbG9ja0hlaWdodDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRmFsbGJhY2s6IGdldCBmcmVzaCBibG9ja2hhc2ggKG1heSB3YWl0IGxvbmdlciB0aGFuIG5lY2Vzc2FyeSBpZiB0eCBhbHJlYWR5IGV4cGlyZWQpXG4gICAgICBjb25zdCBsYXRlc3RCbG9ja2hhc2ggPSBhd2FpdCBwcm92aWRlci5jb25uZWN0aW9uLmdldExhdGVzdEJsb2NraGFzaCgnY29uZmlybWVkJyk7XG4gICAgICBibG9ja2hhc2ggPSBsYXRlc3RCbG9ja2hhc2guYmxvY2toYXNoO1xuICAgICAgbGFzdFZhbGlkQmxvY2tIZWlnaHQgPSBsYXRlc3RCbG9ja2hhc2gubGFzdFZhbGlkQmxvY2tIZWlnaHQ7XG4gICAgfVxuXG4gICAgY29uc3Qgc2lnbmF0dXJlID0gYXdhaXQgcHJvdmlkZXIuY29ubmVjdGlvbi5zZW5kVHJhbnNhY3Rpb24oc2lnbmVkVHgsIHtcbiAgICAgIHNraXBQcmVmbGlnaHQ6IGZhbHNlLFxuICAgICAgcHJlZmxpZ2h0Q29tbWl0bWVudDogJ2NvbmZpcm1lZCcsXG4gICAgfSk7XG5cbiAgICAvLyBVc2UgYmxvY2toYXNoLWJhc2VkIGNvbmZpcm1hdGlvbiB3aGljaCB3YWl0cyB1bnRpbCBlaXRoZXI6XG4gICAgLy8gMS4gVHJhbnNhY3Rpb24gaXMgY29uZmlybWVkXG4gICAgLy8gMi4gQmxvY2toYXNoIGV4cGlyZXMgKGxhc3RWYWxpZEJsb2NrSGVpZ2h0IHBhc3NlZClcbiAgICAvLyBUaGlzIGlzIG1vcmUgcm9idXN0IHRoYW4gYSBmaXhlZCB0aW1lb3V0IG9uIGNvbmdlc3RlZCBuZXR3b3Jrc1xuICAgIGF3YWl0IHByb3ZpZGVyLmNvbm5lY3Rpb24uY29uZmlybVRyYW5zYWN0aW9uKHtcbiAgICAgIHNpZ25hdHVyZSxcbiAgICAgIGJsb2NraGFzaCxcbiAgICAgIGxhc3RWYWxpZEJsb2NrSGVpZ2h0LFxuICAgIH0sICdjb25maXJtZWQnKTtcblxuICAgIHJldHVybiBzaWduYXR1cmU7XG4gIH1cblxuICAvKiBBZGRyZXNzIExvb2t1cCBUYWJsZSAqL1xuXG4gIGFzeW5jIGNyZWF0ZVByb3Bvc2FsQUxUKFxuICAgIGNyZWF0b3I6IFB1YmxpY0tleSxcbiAgICBtb2RlcmF0b3JQZGE6IFB1YmxpY0tleSxcbiAgICBudW1PcHRpb25zOiBudW1iZXIgPSAyLFxuICApOiBQcm9taXNlPHsgYWx0QWRkcmVzczogUHVibGljS2V5IH0+IHtcbiAgICBjb25zdCBwcm92aWRlciA9IHRoaXMucHJvZ3JhbS5wcm92aWRlciBhcyBBbmNob3JQcm92aWRlcjtcbiAgICBjb25zdCBtb2RlcmF0b3IgPSBhd2FpdCB0aGlzLmZldGNoTW9kZXJhdG9yKG1vZGVyYXRvclBkYSk7XG4gICAgY29uc3QgcHJvcG9zYWxJZCA9IG1vZGVyYXRvci5wcm9wb3NhbElkQ291bnRlcjtcbiAgICBjb25zdCBbcHJvcG9zYWxQZGFdID0gdGhpcy5kZXJpdmVQcm9wb3NhbFBEQShtb2RlcmF0b3JQZGEsIHByb3Bvc2FsSWQpO1xuICAgIGNvbnN0IFt2YXVsdFBkYV0gPSBkZXJpdmVWYXVsdFBEQShwcm9wb3NhbFBkYSwgcHJvcG9zYWxJZCwgdGhpcy52YXVsdC5wcm9ncmFtSWQpO1xuXG4gICAgY29uc3QgYWRkcmVzc2VzOiBQdWJsaWNLZXlbXSA9IFtcbiAgICAgIC8vIFByb2dyYW1zXG4gICAgICB0aGlzLnByb2dyYW1JZCxcbiAgICAgIHRoaXMudmF1bHQucHJvZ3JhbUlkLFxuICAgICAgdGhpcy5hbW0ucHJvZ3JhbUlkLFxuICAgICAgU3lzdGVtUHJvZ3JhbS5wcm9ncmFtSWQsXG4gICAgICBUT0tFTl9QUk9HUkFNX0lELFxuICAgICAgQVNTT0NJQVRFRF9UT0tFTl9QUk9HUkFNX0lELFxuICAgICAgLy8gQ29yZSBhY2NvdW50c1xuICAgICAgbW9kZXJhdG9yUGRhLFxuICAgICAgcHJvcG9zYWxQZGEsXG4gICAgICB2YXVsdFBkYSxcbiAgICAgIG1vZGVyYXRvci5iYXNlTWludCxcbiAgICAgIG1vZGVyYXRvci5xdW90ZU1pbnQsXG4gICAgICBGRUVfQVVUSE9SSVRZLFxuICAgICAgLy8gVmF1bHQgdG9rZW4gYWNjb3VudHNcbiAgICAgIGdldEFzc29jaWF0ZWRUb2tlbkFkZHJlc3NTeW5jKG1vZGVyYXRvci5iYXNlTWludCwgdmF1bHRQZGEsIHRydWUpLFxuICAgICAgZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmMobW9kZXJhdG9yLnF1b3RlTWludCwgdmF1bHRQZGEsIHRydWUpLFxuICAgICAgLy8gQ3JlYXRvcidzIGJhc2UvcXVvdGUgQVRBc1xuICAgICAgZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmMobW9kZXJhdG9yLmJhc2VNaW50LCBjcmVhdG9yKSxcbiAgICAgIGdldEFzc29jaWF0ZWRUb2tlbkFkZHJlc3NTeW5jKG1vZGVyYXRvci5xdW90ZU1pbnQsIGNyZWF0b3IpLFxuICAgIF07XG5cbiAgICAvLyBQZXItb3B0aW9uIGFjY291bnRzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1PcHRpb25zOyBpKyspIHtcbiAgICAgIGNvbnN0IFtjb25kQmFzZU1pbnRdID0gZGVyaXZlQ29uZGl0aW9uYWxNaW50KHZhdWx0UGRhLCBWYXVsdFR5cGUuQmFzZSwgaSwgdGhpcy52YXVsdC5wcm9ncmFtSWQpO1xuICAgICAgY29uc3QgW2NvbmRRdW90ZU1pbnRdID0gZGVyaXZlQ29uZGl0aW9uYWxNaW50KHZhdWx0UGRhLCBWYXVsdFR5cGUuUXVvdGUsIGksIHRoaXMudmF1bHQucHJvZ3JhbUlkKTtcbiAgICAgIGNvbnN0IFtwb29sXSA9IGRlcml2ZVBvb2xQREEocHJvcG9zYWxQZGEsIGNvbmRRdW90ZU1pbnQsIGNvbmRCYXNlTWludCwgdGhpcy5hbW0ucHJvZ3JhbUlkKTtcbiAgICAgIGNvbnN0IFtyZXNlcnZlQV0gPSBkZXJpdmVSZXNlcnZlUERBKHBvb2wsIGNvbmRRdW90ZU1pbnQsIHRoaXMuYW1tLnByb2dyYW1JZCk7XG4gICAgICBjb25zdCBbcmVzZXJ2ZUJdID0gZGVyaXZlUmVzZXJ2ZVBEQShwb29sLCBjb25kQmFzZU1pbnQsIHRoaXMuYW1tLnByb2dyYW1JZCk7XG4gICAgICBjb25zdCBbZmVlVmF1bHRdID0gZGVyaXZlRmVlVmF1bHRQREEocG9vbCwgdGhpcy5hbW0ucHJvZ3JhbUlkKTtcblxuICAgICAgYWRkcmVzc2VzLnB1c2goXG4gICAgICAgIGNvbmRCYXNlTWludCxcbiAgICAgICAgY29uZFF1b3RlTWludCxcbiAgICAgICAgcG9vbCxcbiAgICAgICAgcmVzZXJ2ZUEsXG4gICAgICAgIHJlc2VydmVCLFxuICAgICAgICBmZWVWYXVsdCxcbiAgICAgICAgLy8gQ3JlYXRvcidzIGNvbmRpdGlvbmFsIHRva2VuIEFUQXNcbiAgICAgICAgZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmMoY29uZEJhc2VNaW50LCBjcmVhdG9yKSxcbiAgICAgICAgZ2V0QXNzb2NpYXRlZFRva2VuQWRkcmVzc1N5bmMoY29uZFF1b3RlTWludCwgY3JlYXRvciksXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIEdldCB0aGUgbW9zdCByZWNlbnQgc2xvdCB1c2luZyBcImZpbmFsaXplZFwiIGNvbW1pdG1lbnQgZm9yIHN0YWJpbGl0eVxuICAgIGNvbnN0IHNsb3QgPSBhd2FpdCBwcm92aWRlci5jb25uZWN0aW9uLmdldFNsb3QoXCJmaW5hbGl6ZWRcIik7XG5cbiAgICBjb25zdCBbY3JlYXRlSXgsIGFsdEFkZHJlc3NdID0gQWRkcmVzc0xvb2t1cFRhYmxlUHJvZ3JhbS5jcmVhdGVMb29rdXBUYWJsZSh7XG4gICAgICBhdXRob3JpdHk6IGNyZWF0b3IsXG4gICAgICBwYXllcjogY3JlYXRvcixcbiAgICAgIHJlY2VudFNsb3Q6IHNsb3QsXG4gICAgfSk7XG5cbiAgICAvLyBTZW5kIGNyZWF0ZSB0cmFuc2FjdGlvbiBpbW1lZGlhdGVseSwgc2tpcCBwcmVmbGlnaHQgdG8gYXZvaWQgc2xvdCB0aW1pbmcgaXNzdWVzXG4gICAgY29uc3QgY3JlYXRlVHggPSBuZXcgVHJhbnNhY3Rpb24oKS5hZGQoY3JlYXRlSXgpO1xuICAgIGNvbnN0IHsgYmxvY2toYXNoOiBjcmVhdGVCbG9ja2hhc2gsIGxhc3RWYWxpZEJsb2NrSGVpZ2h0OiBjcmVhdGVMYXN0VmFsaWRCbG9ja0hlaWdodCB9ID1cbiAgICAgIGF3YWl0IHByb3ZpZGVyLmNvbm5lY3Rpb24uZ2V0TGF0ZXN0QmxvY2toYXNoKCdjb25maXJtZWQnKTtcbiAgICBjcmVhdGVUeC5yZWNlbnRCbG9ja2hhc2ggPSBjcmVhdGVCbG9ja2hhc2g7XG4gICAgY3JlYXRlVHguZmVlUGF5ZXIgPSBjcmVhdG9yO1xuICAgIGNvbnN0IHNpZ25lZFR4ID0gYXdhaXQgcHJvdmlkZXIud2FsbGV0LnNpZ25UcmFuc2FjdGlvbihjcmVhdGVUeCk7XG4gICAgY29uc3Qgc2lnID0gYXdhaXQgcHJvdmlkZXIuY29ubmVjdGlvbi5zZW5kUmF3VHJhbnNhY3Rpb24oc2lnbmVkVHguc2VyaWFsaXplKCksIHtcbiAgICAgIHNraXBQcmVmbGlnaHQ6IHRydWUsXG4gICAgfSk7XG4gICAgYXdhaXQgcHJvdmlkZXIuY29ubmVjdGlvbi5jb25maXJtVHJhbnNhY3Rpb24oe1xuICAgICAgc2lnbmF0dXJlOiBzaWcsXG4gICAgICBibG9ja2hhc2g6IGNyZWF0ZUJsb2NraGFzaCxcbiAgICAgIGxhc3RWYWxpZEJsb2NrSGVpZ2h0OiBjcmVhdGVMYXN0VmFsaWRCbG9ja0hlaWdodCxcbiAgICB9LCBcImNvbmZpcm1lZFwiKTtcblxuICAgIC8vIFNwbGl0IGFkZHJlc3NlcyBpbnRvIGNodW5rcyB0byBhdm9pZCB0cmFuc2FjdGlvbiBzaXplIGxpbWl0c1xuICAgIC8vIEVhY2ggYWRkcmVzcyBpcyAzMiBieXRlcywgfjIwIGFkZHJlc3NlcyBwZXIgZXh0ZW5kIGluc3RydWN0aW9uIGlzIHNhZmVcbiAgICAvLyBVc2Ugc2tpcFByZWZsaWdodCB0byBhdm9pZCByYWNlIGNvbmRpdGlvbiB3aGVyZSBzaW11bGF0aW9uIHNlZXMgc3RhbGUgc3RhdGVcbiAgICAvLyBiZWZvcmUgcHJldmlvdXMgZXh0ZW5kIGhhcyBwcm9wYWdhdGVkIChzYW1lIHBhdHRlcm4gYXMgQ1JFQVRFIGFib3ZlKVxuICAgIGNvbnN0IENIVU5LX1NJWkUgPSAyMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFkZHJlc3Nlcy5sZW5ndGg7IGkgKz0gQ0hVTktfU0laRSkge1xuICAgICAgY29uc3QgY2h1bmsgPSBhZGRyZXNzZXMuc2xpY2UoaSwgaSArIENIVU5LX1NJWkUpO1xuICAgICAgY29uc3QgZXh0ZW5kSXggPSBBZGRyZXNzTG9va3VwVGFibGVQcm9ncmFtLmV4dGVuZExvb2t1cFRhYmxlKHtcbiAgICAgICAgcGF5ZXI6IGNyZWF0b3IsXG4gICAgICAgIGF1dGhvcml0eTogY3JlYXRvcixcbiAgICAgICAgbG9va3VwVGFibGU6IGFsdEFkZHJlc3MsXG4gICAgICAgIGFkZHJlc3NlczogY2h1bmssXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGV4dGVuZFR4ID0gbmV3IFRyYW5zYWN0aW9uKCkuYWRkKGV4dGVuZEl4KTtcbiAgICAgIGNvbnN0IHsgYmxvY2toYXNoOiBleHRlbmRCbG9ja2hhc2gsIGxhc3RWYWxpZEJsb2NrSGVpZ2h0OiBleHRlbmRMYXN0VmFsaWRCbG9ja0hlaWdodCB9ID1cbiAgICAgICAgYXdhaXQgcHJvdmlkZXIuY29ubmVjdGlvbi5nZXRMYXRlc3RCbG9ja2hhc2goJ2NvbmZpcm1lZCcpO1xuICAgICAgZXh0ZW5kVHgucmVjZW50QmxvY2toYXNoID0gZXh0ZW5kQmxvY2toYXNoO1xuICAgICAgZXh0ZW5kVHguZmVlUGF5ZXIgPSBjcmVhdG9yO1xuICAgICAgY29uc3Qgc2lnbmVkRXh0ZW5kVHggPSBhd2FpdCBwcm92aWRlci53YWxsZXQuc2lnblRyYW5zYWN0aW9uKGV4dGVuZFR4KTtcbiAgICAgIGNvbnN0IGV4dGVuZFNpZyA9IGF3YWl0IHByb3ZpZGVyLmNvbm5lY3Rpb24uc2VuZFJhd1RyYW5zYWN0aW9uKHNpZ25lZEV4dGVuZFR4LnNlcmlhbGl6ZSgpLCB7XG4gICAgICAgIHNraXBQcmVmbGlnaHQ6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHByb3ZpZGVyLmNvbm5lY3Rpb24uY29uZmlybVRyYW5zYWN0aW9uKHtcbiAgICAgICAgc2lnbmF0dXJlOiBleHRlbmRTaWcsXG4gICAgICAgIGJsb2NraGFzaDogZXh0ZW5kQmxvY2toYXNoLFxuICAgICAgICBsYXN0VmFsaWRCbG9ja0hlaWdodDogZXh0ZW5kTGFzdFZhbGlkQmxvY2tIZWlnaHQsXG4gICAgICB9LCBcImNvbmZpcm1lZFwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBhbHRBZGRyZXNzIH07XG4gIH1cblxuICBhc3luYyBmZXRjaEFMVChhbHRBZGRyZXNzOiBQdWJsaWNLZXkpOiBQcm9taXNlPEFkZHJlc3NMb29rdXBUYWJsZUFjY291bnQ+IHtcbiAgICBjb25zdCBhbHQgPSBhd2FpdCB0aGlzLnByb2dyYW0ucHJvdmlkZXIuY29ubmVjdGlvbi5nZXRBZGRyZXNzTG9va3VwVGFibGUoYWx0QWRkcmVzcyk7XG4gICAgaWYgKCFhbHQudmFsdWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkFMVCBub3QgZm91bmRcIik7XG4gICAgfVxuICAgIHJldHVybiBhbHQudmFsdWU7XG4gIH1cblxuICBhc3luYyBidWlsZFZlcnNpb25lZFR4KFxuICAgIHBheWVyOiBQdWJsaWNLZXksXG4gICAgaW5zdHJ1Y3Rpb25zOiBUcmFuc2FjdGlvbkluc3RydWN0aW9uW10sXG4gICAgYWx0QWRkcmVzczogUHVibGljS2V5LFxuICApOiBQcm9taXNlPHtcbiAgICB2ZXJzaW9uZWRUeDogVmVyc2lvbmVkVHJhbnNhY3Rpb247XG4gICAgYmxvY2toYXNoOiBzdHJpbmc7XG4gICAgbGFzdFZhbGlkQmxvY2tIZWlnaHQ6IG51bWJlcjtcbiAgfT4ge1xuICAgIGNvbnN0IHByb3ZpZGVyID0gdGhpcy5wcm9ncmFtLnByb3ZpZGVyIGFzIEFuY2hvclByb3ZpZGVyO1xuICAgIGNvbnN0IGFsdCA9IGF3YWl0IHRoaXMuZmV0Y2hBTFQoYWx0QWRkcmVzcyk7XG4gICAgY29uc3QgeyBibG9ja2hhc2gsIGxhc3RWYWxpZEJsb2NrSGVpZ2h0IH0gPSBhd2FpdCBwcm92aWRlci5jb25uZWN0aW9uLmdldExhdGVzdEJsb2NraGFzaCgnY29uZmlybWVkJyk7XG4gICAgY29uc3QgdmVyc2lvbmVkVHggPSB0aGlzLmJ1aWxkVmVyc2lvbmVkVHhXaXRoQUxUKHBheWVyLCBpbnN0cnVjdGlvbnMsIGFsdCwgYmxvY2toYXNoKTtcbiAgICByZXR1cm4geyB2ZXJzaW9uZWRUeCwgYmxvY2toYXNoLCBsYXN0VmFsaWRCbG9ja0hlaWdodCB9O1xuICB9XG5cbiAgYnVpbGRWZXJzaW9uZWRUeFdpdGhBTFQoXG4gICAgcGF5ZXI6IFB1YmxpY0tleSxcbiAgICBpbnN0cnVjdGlvbnM6IFRyYW5zYWN0aW9uSW5zdHJ1Y3Rpb25bXSxcbiAgICBhbHQ6IEFkZHJlc3NMb29rdXBUYWJsZUFjY291bnQsXG4gICAgYmxvY2toYXNoOiBzdHJpbmcsXG4gICk6IFZlcnNpb25lZFRyYW5zYWN0aW9uIHtcbiAgICBjb25zdCBtZXNzYWdlID0gbmV3IFRyYW5zYWN0aW9uTWVzc2FnZSh7XG4gICAgICBwYXllcktleTogcGF5ZXIsXG4gICAgICByZWNlbnRCbG9ja2hhc2g6IGJsb2NraGFzaCxcbiAgICAgIGluc3RydWN0aW9ucyxcbiAgICB9KS5jb21waWxlVG9WME1lc3NhZ2UoW2FsdF0pO1xuXG4gICAgcmV0dXJuIG5ldyBWZXJzaW9uZWRUcmFuc2FjdGlvbihtZXNzYWdlKTtcbiAgfVxuXG4gIC8qIERBTyBNZXRob2RzICovXG5cbiAgZGVyaXZlTWludENyZWF0ZUtleVBEQShkYW9QZGE6IFB1YmxpY0tleSwgbmFtZTogc3RyaW5nKTogW1B1YmxpY0tleSwgbnVtYmVyXSB7XG4gICAgcmV0dXJuIGRlcml2ZU1pbnRDcmVhdGVLZXlQREEoZGFvUGRhLCBuYW1lLCB0aGlzLnByb2dyYW1JZCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoU3F1YWRzUHJvZ3JhbUNvbmZpZygpIHtcbiAgICBjb25zdCBbcHJvZ3JhbUNvbmZpZ1BkYV0gPSBtdWx0aXNpZy5nZXRQcm9ncmFtQ29uZmlnUGRhKHtcbiAgICAgIHByb2dyYW1JZDogU1FVQURTX1BST0dSQU1fSUQsXG4gICAgfSk7XG4gICAgY29uc3QgcHJvZ3JhbUNvbmZpZyA9IGF3YWl0IG11bHRpc2lnLmFjY291bnRzLlByb2dyYW1Db25maWcuZnJvbUFjY291bnRBZGRyZXNzKFxuICAgICAgdGhpcy5wcm9ncmFtLnByb3ZpZGVyLmNvbm5lY3Rpb24sXG4gICAgICBwcm9ncmFtQ29uZmlnUGRhXG4gICAgKTtcbiAgICByZXR1cm4ge1xuICAgICAgcHJvZ3JhbUNvbmZpZzogcHJvZ3JhbUNvbmZpZ1BkYSxcbiAgICAgIHByb2dyYW1Db25maWdUcmVhc3VyeTogcHJvZ3JhbUNvbmZpZy50cmVhc3VyeSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBkZXJpdmVNdWx0aXNpZ1BkYShjcmVhdGVLZXk6IFB1YmxpY0tleSk6IFB1YmxpY0tleSB7XG4gICAgY29uc3QgW211bHRpc2lnUGRhXSA9IG11bHRpc2lnLmdldE11bHRpc2lnUGRhKHtcbiAgICAgIGNyZWF0ZUtleSxcbiAgICAgIHByb2dyYW1JZDogU1FVQURTX1BST0dSQU1fSUQsXG4gICAgfSk7XG4gICAgcmV0dXJuIG11bHRpc2lnUGRhO1xuICB9XG5cbiAgYXN5bmMgaW5pdGlhbGl6ZVBhcmVudERBTyhcbiAgICBhZG1pbjogUHVibGljS2V5LFxuICAgIHBhcmVudEFkbWluOiBQdWJsaWNLZXksXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGJhc2VNaW50OiBQdWJsaWNLZXksXG4gICAgcXVvdGVNaW50OiBQdWJsaWNLZXksXG4gICAgdHJlYXN1cnlDb3NpZ25lcjogUHVibGljS2V5LFxuICAgIHBvb2w6IFB1YmxpY0tleSxcbiAgICBwb29sVHlwZTogUG9vbFR5cGUsXG4gICAgb3B0aW9ucz86IFR4T3B0aW9uc1xuICApIHtcbiAgICBjb25zdCBbZGFvUGRhXSA9IHRoaXMuZGVyaXZlREFPUERBKG5hbWUpO1xuICAgIGNvbnN0IFttb2RlcmF0b3JQZGFdID0gdGhpcy5kZXJpdmVNb2RlcmF0b3JQREEobmFtZSk7XG4gICAgY29uc3QgW21pbnRDcmVhdGVLZXlQZGFdID0gdGhpcy5kZXJpdmVNaW50Q3JlYXRlS2V5UERBKGRhb1BkYSwgbmFtZSk7XG5cbiAgICAvLyBEZXJpdmUgU3F1YWRzIGFjY291bnRzIChzaW5nbGUgUlBDIGNhbGwpXG4gICAgY29uc3Qgc3F1YWRzQ29uZmlnID0gYXdhaXQgdGhpcy5mZXRjaFNxdWFkc1Byb2dyYW1Db25maWcoKTtcbiAgICBjb25zdCB0cmVhc3VyeU11bHRpc2lnUGRhID0gdGhpcy5kZXJpdmVNdWx0aXNpZ1BkYShkYW9QZGEpO1xuICAgIGNvbnN0IG1pbnRNdWx0aXNpZ1BkYSA9IHRoaXMuZGVyaXZlTXVsdGlzaWdQZGEobWludENyZWF0ZUtleVBkYSk7XG5cbiAgICBjb25zdCBidWlsZGVyID0gaW5pdGlhbGl6ZVBhcmVudERBTyhcbiAgICAgIHRoaXMucHJvZ3JhbSxcbiAgICAgIGFkbWluLFxuICAgICAgcGFyZW50QWRtaW4sXG4gICAgICBkYW9QZGEsXG4gICAgICBtb2RlcmF0b3JQZGEsXG4gICAgICBiYXNlTWludCxcbiAgICAgIHF1b3RlTWludCxcbiAgICAgIHNxdWFkc0NvbmZpZy5wcm9ncmFtQ29uZmlnLFxuICAgICAgc3F1YWRzQ29uZmlnLnByb2dyYW1Db25maWdUcmVhc3VyeSxcbiAgICAgIHRyZWFzdXJ5TXVsdGlzaWdQZGEsXG4gICAgICBtaW50TXVsdGlzaWdQZGEsXG4gICAgICBtaW50Q3JlYXRlS2V5UGRhLFxuICAgICAgU1FVQURTX1BST0dSQU1fSUQsXG4gICAgICBuYW1lLFxuICAgICAgdHJlYXN1cnlDb3NpZ25lcixcbiAgICAgIHBvb2wsXG4gICAgICBwb29sVHlwZVxuICAgICkucHJlSW5zdHJ1Y3Rpb25zKHRoaXMubWF5YmVBZGRDb21wdXRlQnVkZ2V0KG9wdGlvbnMpKTtcblxuICAgIHJldHVybiB7XG4gICAgICBidWlsZGVyLFxuICAgICAgZGFvUGRhLFxuICAgICAgbW9kZXJhdG9yUGRhLFxuICAgICAgdHJlYXN1cnlNdWx0aXNpZzogdHJlYXN1cnlNdWx0aXNpZ1BkYSxcbiAgICAgIG1pbnRNdWx0aXNpZzogbWludE11bHRpc2lnUGRhLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBpbml0aWFsaXplQ2hpbGREQU8oXG4gICAgYWRtaW46IFB1YmxpY0tleSxcbiAgICBwYXJlbnRBZG1pbjogUHVibGljS2V5LFxuICAgIHBhcmVudERhb05hbWU6IHN0cmluZyxcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgdG9rZW5NaW50OiBQdWJsaWNLZXksXG4gICAgdHJlYXN1cnlDb3NpZ25lcjogUHVibGljS2V5LFxuICAgIG9wdGlvbnM/OiBUeE9wdGlvbnNcbiAgKSB7XG4gICAgY29uc3QgW2Rhb1BkYV0gPSB0aGlzLmRlcml2ZURBT1BEQShuYW1lKTtcbiAgICBjb25zdCBbcGFyZW50RGFvUGRhXSA9IHRoaXMuZGVyaXZlREFPUERBKHBhcmVudERhb05hbWUpO1xuICAgIGNvbnN0IFttaW50Q3JlYXRlS2V5UGRhXSA9IHRoaXMuZGVyaXZlTWludENyZWF0ZUtleVBEQShkYW9QZGEsIG5hbWUpO1xuXG4gICAgLy8gRGVyaXZlIFNxdWFkcyBhY2NvdW50cyAoc2luZ2xlIFJQQyBjYWxsKVxuICAgIGNvbnN0IHNxdWFkc0NvbmZpZyA9IGF3YWl0IHRoaXMuZmV0Y2hTcXVhZHNQcm9ncmFtQ29uZmlnKCk7XG4gICAgY29uc3QgdHJlYXN1cnlNdWx0aXNpZ1BkYSA9IHRoaXMuZGVyaXZlTXVsdGlzaWdQZGEoZGFvUGRhKTtcbiAgICBjb25zdCBtaW50TXVsdGlzaWdQZGEgPSB0aGlzLmRlcml2ZU11bHRpc2lnUGRhKG1pbnRDcmVhdGVLZXlQZGEpO1xuXG4gICAgY29uc3QgYnVpbGRlciA9IGluaXRpYWxpemVDaGlsZERBTyhcbiAgICAgIHRoaXMucHJvZ3JhbSxcbiAgICAgIGFkbWluLFxuICAgICAgcGFyZW50QWRtaW4sXG4gICAgICBkYW9QZGEsXG4gICAgICBwYXJlbnREYW9QZGEsXG4gICAgICB0b2tlbk1pbnQsXG4gICAgICBzcXVhZHNDb25maWcucHJvZ3JhbUNvbmZpZyxcbiAgICAgIHNxdWFkc0NvbmZpZy5wcm9ncmFtQ29uZmlnVHJlYXN1cnksXG4gICAgICB0cmVhc3VyeU11bHRpc2lnUGRhLFxuICAgICAgbWludE11bHRpc2lnUGRhLFxuICAgICAgbWludENyZWF0ZUtleVBkYSxcbiAgICAgIFNRVUFEU19QUk9HUkFNX0lELFxuICAgICAgbmFtZSxcbiAgICAgIHRyZWFzdXJ5Q29zaWduZXJcbiAgICApLnByZUluc3RydWN0aW9ucyh0aGlzLm1heWJlQWRkQ29tcHV0ZUJ1ZGdldChvcHRpb25zKSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgYnVpbGRlcixcbiAgICAgIGRhb1BkYSxcbiAgICAgIHBhcmVudERhb1BkYSxcbiAgICAgIHRyZWFzdXJ5TXVsdGlzaWc6IHRyZWFzdXJ5TXVsdGlzaWdQZGEsXG4gICAgICBtaW50TXVsdGlzaWc6IG1pbnRNdWx0aXNpZ1BkYSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgdXBncmFkZURBTyhcbiAgICBhZG1pbjogUHVibGljS2V5LFxuICAgIHBhcmVudEFkbWluOiBQdWJsaWNLZXksXG4gICAgZGFvTmFtZTogc3RyaW5nLFxuICAgIHBhcmVudERhb05hbWU6IHN0cmluZyxcbiAgICBiYXNlTWludDogUHVibGljS2V5LFxuICAgIHF1b3RlTWludDogUHVibGljS2V5LFxuICAgIHBvb2w6IFB1YmxpY0tleSxcbiAgICBwb29sVHlwZTogUG9vbFR5cGUsXG4gICAgb3B0aW9ucz86IFR4T3B0aW9uc1xuICApIHtcbiAgICBjb25zdCBbZGFvUGRhXSA9IHRoaXMuZGVyaXZlREFPUERBKGRhb05hbWUpO1xuICAgIGNvbnN0IFtwYXJlbnREYW9QZGFdID0gdGhpcy5kZXJpdmVEQU9QREEocGFyZW50RGFvTmFtZSk7XG4gICAgY29uc3QgW21vZGVyYXRvclBkYV0gPSB0aGlzLmRlcml2ZU1vZGVyYXRvclBEQShkYW9OYW1lKTtcblxuICAgIGNvbnN0IGJ1aWxkZXIgPSB1cGdyYWRlREFPKFxuICAgICAgdGhpcy5wcm9ncmFtLFxuICAgICAgYWRtaW4sXG4gICAgICBwYXJlbnRBZG1pbixcbiAgICAgIGRhb1BkYSxcbiAgICAgIHBhcmVudERhb1BkYSxcbiAgICAgIG1vZGVyYXRvclBkYSxcbiAgICAgIGJhc2VNaW50LFxuICAgICAgcXVvdGVNaW50LFxuICAgICAgcG9vbCxcbiAgICAgIHBvb2xUeXBlXG4gICAgKS5wcmVJbnN0cnVjdGlvbnModGhpcy5tYXliZUFkZENvbXB1dGVCdWRnZXQob3B0aW9ucykpO1xuXG4gICAgcmV0dXJuIHsgYnVpbGRlciwgZGFvUGRhLCBtb2RlcmF0b3JQZGEgfTtcbiAgfVxuXG4gIGFzeW5jIGFkZEhpc3RvcmljYWxQYXJlbnREQU8oXG4gICAgYWRtaW46IFB1YmxpY0tleSxcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgYmFzZU1pbnQ6IFB1YmxpY0tleSxcbiAgICBxdW90ZU1pbnQ6IFB1YmxpY0tleSxcbiAgICB0cmVhc3VyeU11bHRpc2lnOiBQdWJsaWNLZXksXG4gICAgbWludEF1dGhNdWx0aXNpZzogUHVibGljS2V5LFxuICAgIGNvc2lnbmVyOiBQdWJsaWNLZXksXG4gICAgcG9vbDogUHVibGljS2V5LFxuICAgIHBvb2xUeXBlOiBQb29sVHlwZSxcbiAgICBwcm9wb3NhbElkQ291bnRlcjogbnVtYmVyLFxuICAgIGFkbWluUHVia2V5OiBQdWJsaWNLZXksXG4gICAgb3B0aW9ucz86IFR4T3B0aW9uc1xuICApIHtcbiAgICBjb25zdCBbZGFvUGRhXSA9IHRoaXMuZGVyaXZlREFPUERBKG5hbWUpO1xuICAgIGNvbnN0IFttb2RlcmF0b3JQZGFdID0gdGhpcy5kZXJpdmVNb2RlcmF0b3JQREEobmFtZSk7XG5cbiAgICBjb25zdCBidWlsZGVyID0gYWRkSGlzdG9yaWNhbFBhcmVudERBTyhcbiAgICAgIHRoaXMucHJvZ3JhbSxcbiAgICAgIGFkbWluLFxuICAgICAgZGFvUGRhLFxuICAgICAgbW9kZXJhdG9yUGRhLFxuICAgICAgdHJlYXN1cnlNdWx0aXNpZyxcbiAgICAgIG1pbnRBdXRoTXVsdGlzaWcsXG4gICAgICBiYXNlTWludCxcbiAgICAgIHF1b3RlTWludCxcbiAgICAgIG5hbWUsXG4gICAgICBjb3NpZ25lcixcbiAgICAgIHBvb2wsXG4gICAgICBwb29sVHlwZSxcbiAgICAgIHByb3Bvc2FsSWRDb3VudGVyLFxuICAgICAgYWRtaW5QdWJrZXlcbiAgICApLnByZUluc3RydWN0aW9ucyh0aGlzLm1heWJlQWRkQ29tcHV0ZUJ1ZGdldChvcHRpb25zKSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgYnVpbGRlcixcbiAgICAgIGRhb1BkYSxcbiAgICAgIG1vZGVyYXRvclBkYSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgdHJhbnNmZXJBZG1pbihcbiAgICBhZG1pbjogUHVibGljS2V5LFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBuZXdBZG1pbjogUHVibGljS2V5LFxuICAgIG9wdGlvbnM/OiBUeE9wdGlvbnNcbiAgKSB7XG4gICAgY29uc3QgW2Rhb1BkYV0gPSB0aGlzLmRlcml2ZURBT1BEQShuYW1lKTtcbiAgICBjb25zdCBbbW9kZXJhdG9yUGRhXSA9IHRoaXMuZGVyaXZlTW9kZXJhdG9yUERBKG5hbWUpO1xuXG4gICAgY29uc3QgYnVpbGRlciA9IHRyYW5zZmVyQWRtaW4oXG4gICAgICB0aGlzLnByb2dyYW0sXG4gICAgICBhZG1pbixcbiAgICAgIGRhb1BkYSxcbiAgICAgIG1vZGVyYXRvclBkYSxcbiAgICAgIG5ld0FkbWluXG4gICAgKS5wcmVJbnN0cnVjdGlvbnModGhpcy5tYXliZUFkZENvbXB1dGVCdWRnZXQob3B0aW9ucykpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGJ1aWxkZXIsXG4gICAgICBkYW9QZGEsXG4gICAgICBtb2RlcmF0b3JQZGEsXG4gICAgfTtcbiAgfVxufVxuIl19
1
+ "use strict";var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,i,s){void 0===s&&(s=i);var r=Object.getOwnPropertyDescriptor(t,i);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,s,r)}:function(e,t,i,s){void 0===s&&(s=i),e[s]=t[i]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(e){var t=[];for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[t.length]=i);return t},e(t)};return function(t){if(t&&t.__esModule)return t;var i={};if(null!=t)for(var s=e(t),r=0;r<s.length;r++)"default"!==s[r]&&__createBinding(i,t,s[r]);return __setModuleDefault(i,t),i}}();Object.defineProperty(exports,"__esModule",{value:!0}),exports.FutarchyClient=void 0;const anchor_1=require("@coral-xyz/anchor"),web3_js_1=require("@solana/web3.js"),spl_token_1=require("@solana/spl-token"),constants_1=require("./constants"),utils_1=require("./utils"),instructions_1=require("./instructions"),vault_1=require("../vault"),amm_1=require("../amm"),idls_1=require("../generated/idls"),multisig=__importStar(require("@sqds/multisig")),DEFAULT_COMPUTE_UNITS=5e5;class FutarchyClient{constructor(e,t,i){this.programId=t??constants_1.PROGRAM_ID,this.program=new anchor_1.Program(idls_1.FutarchyIDL,e),this.vault=new vault_1.VaultClient(e),this.amm=new amm_1.AMMClient(e),this.defaultComputeUnits=i??5e5}deriveDAOPDA(e){return(0,utils_1.deriveDAOPDA)(e,this.programId)}deriveModeratorPDA(e){return(0,utils_1.deriveModeratorPDA)(e,this.programId)}deriveProposalPDA(e,t){return(0,utils_1.deriveProposalPDA)(e,t,this.programId)}async fetchDAO(e){return(0,utils_1.fetchDAOAccount)(this.program,e)}async fetchModerator(e){return(0,utils_1.fetchModeratorAccount)(this.program,e)}async fetchProposal(e){return(0,utils_1.fetchProposalAccount)(this.program,e)}isProposalExpired(e){return(0,utils_1.isProposalExpired)(e)}getTimeRemaining(e){return(0,utils_1.getTimeRemaining)(e)}getComputeUnits(e){return e?.computeUnits??this.defaultComputeUnits}maybeAddComputeBudget(e){if(!1===e?.includeCuBudget)return[];const t=[web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({units:this.getComputeUnits(e)})];return void 0!==e?.priorityFeeMicroLamports&&e.priorityFeeMicroLamports>0&&t.push(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({microLamports:e.priorityFeeMicroLamports})),t}async initializeModerator(e,t,i,s,r){const[a]=this.deriveModeratorPDA(s);return{builder:(0,instructions_1.initializeModerator)(this.program,e,t,i,a,s).preInstructions(this.maybeAddComputeBudget(r)),moderatorPda:a,name:s}}async addHistoricalProposal(e,t,i,s,r,a,o,n){const d=(await this.fetchModerator(t)).proposalIdCounter,[l]=this.deriveProposalPDA(t,d);return{builder:(0,instructions_1.addHistoricalProposal)(this.program,e,t,l,i,s,r,a,o).preInstructions(this.maybeAddComputeBudget(n)),proposalPda:l,proposalId:d}}async initializeProposal(e,t,i,s,r){const a=await this.fetchModerator(t),o=a.proposalIdCounter,[n]=this.deriveProposalPDA(t,o),[d]=(0,vault_1.deriveVaultPDA)(n,o,this.vault.programId),[l]=(0,vault_1.deriveConditionalMint)(d,vault_1.VaultType.Base,0,this.vault.programId),[u]=(0,vault_1.deriveConditionalMint)(d,vault_1.VaultType.Base,1,this.vault.programId),[c]=(0,vault_1.deriveConditionalMint)(d,vault_1.VaultType.Quote,0,this.vault.programId),[p]=(0,vault_1.deriveConditionalMint)(d,vault_1.VaultType.Quote,1,this.vault.programId),[m]=(0,amm_1.derivePoolPDA)(n,c,l,this.amm.programId),[g]=(0,amm_1.derivePoolPDA)(n,p,u,this.amm.programId),[h]=(0,amm_1.deriveReservePDA)(m,c,this.amm.programId),[_]=(0,amm_1.deriveReservePDA)(m,l,this.amm.programId),[b]=(0,amm_1.deriveFeeVaultPDA)(m,this.amm.programId),[A]=(0,amm_1.deriveReservePDA)(g,p,this.amm.programId),[k]=(0,amm_1.deriveReservePDA)(g,u,this.amm.programId),[y]=(0,amm_1.deriveFeeVaultPDA)(g,this.amm.programId),v=(0,spl_token_1.getAssociatedTokenAddressSync)(a.baseMint,d,!0),P=(0,spl_token_1.getAssociatedTokenAddressSync)(a.quoteMint,d,!0),f=[{pubkey:a.baseMint,isSigner:!1,isWritable:!1},{pubkey:a.quoteMint,isSigner:!1,isWritable:!1},{pubkey:d,isSigner:!1,isWritable:!0},{pubkey:v,isSigner:!1,isWritable:!0},{pubkey:P,isSigner:!1,isWritable:!0},{pubkey:l,isSigner:!1,isWritable:!0},{pubkey:u,isSigner:!1,isWritable:!0},{pubkey:c,isSigner:!1,isWritable:!0},{pubkey:p,isSigner:!1,isWritable:!0},{pubkey:m,isSigner:!1,isWritable:!0},{pubkey:h,isSigner:!1,isWritable:!0},{pubkey:_,isSigner:!1,isWritable:!0},{pubkey:amm_1.FEE_AUTHORITY,isSigner:!1,isWritable:!1},{pubkey:b,isSigner:!1,isWritable:!0},{pubkey:g,isSigner:!1,isWritable:!0},{pubkey:A,isSigner:!1,isWritable:!0},{pubkey:k,isSigner:!1,isWritable:!0},{pubkey:y,isSigner:!1,isWritable:!0}];return{builder:(0,instructions_1.initializeProposal)(this.program,e,t,n,i,s??null,f).preInstructions(this.maybeAddComputeBudget(r)),proposalPda:n,proposalId:o,vaultPda:d,pools:[m,g],condBaseMints:[l,u],condQuoteMints:[c,p]}}async addOption(e,t,i){const s=await this.fetchProposal(t),r=s.numOptions,[a]=(0,vault_1.deriveConditionalMint)(s.vault,vault_1.VaultType.Base,r,this.vault.programId),[o]=(0,vault_1.deriveConditionalMint)(s.vault,vault_1.VaultType.Quote,r,this.vault.programId),[n]=(0,amm_1.derivePoolPDA)(t,o,a,this.amm.programId),[d]=(0,amm_1.deriveReservePDA)(n,o,this.amm.programId),[l]=(0,amm_1.deriveReservePDA)(n,a,this.amm.programId),[u]=(0,amm_1.deriveFeeVaultPDA)(n,this.amm.programId),c=[{pubkey:s.vault,isSigner:!1,isWritable:!0},{pubkey:a,isSigner:!1,isWritable:!0},{pubkey:o,isSigner:!1,isWritable:!0},{pubkey:n,isSigner:!1,isWritable:!0},{pubkey:d,isSigner:!1,isWritable:!0},{pubkey:l,isSigner:!1,isWritable:!0},{pubkey:amm_1.FEE_AUTHORITY,isSigner:!1,isWritable:!1},{pubkey:u,isSigner:!1,isWritable:!0}];return{builder:(0,instructions_1.addOption)(this.program,e,t,c).preInstructions(this.maybeAddComputeBudget(i)),optionIndex:r,pool:n,condBaseMint:a,condQuoteMint:o}}async launchProposal(e,t,i,s,r){const a=await this.fetchProposal(t),o=await this.vault.fetchVault(a.vault),n=a.numOptions,d=o.condBaseMints.slice(0,n),l=o.condQuoteMints.slice(0,n);(r?.ensureATAs??n>=3)&&await this._createConditionalATAs(e,d,l);const u=a.pools.slice(0,n),c=d.map(t=>(0,spl_token_1.getAssociatedTokenAddressSync)(t,e)),p=l.map(t=>(0,spl_token_1.getAssociatedTokenAddressSync)(t,e)),m=[],g=[];for(let e=0;e<n;e++){const[t]=(0,amm_1.deriveReservePDA)(u[e],l[e],this.amm.programId),[i]=(0,amm_1.deriveReservePDA)(u[e],d[e],this.amm.programId);m.push(t),g.push(i)}const h=[{pubkey:o.baseMint.address,isSigner:!1,isWritable:!1},{pubkey:o.quoteMint.address,isSigner:!1,isWritable:!1},{pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(o.baseMint.address,a.vault,!0),isSigner:!1,isWritable:!0},{pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(o.quoteMint.address,a.vault,!0),isSigner:!1,isWritable:!0},{pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(o.baseMint.address,e),isSigner:!1,isWritable:!0},{pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(o.quoteMint.address,e),isSigner:!1,isWritable:!0}];for(const e of d)h.push({pubkey:e,isSigner:!1,isWritable:!0});for(const e of l)h.push({pubkey:e,isSigner:!1,isWritable:!0});for(const e of c)h.push({pubkey:e,isSigner:!1,isWritable:!0});for(const e of p)h.push({pubkey:e,isSigner:!1,isWritable:!0});for(const e of u)h.push({pubkey:e,isSigner:!1,isWritable:!0});for(const e of m)h.push({pubkey:e,isSigner:!1,isWritable:!0});for(const e of g)h.push({pubkey:e,isSigner:!1,isWritable:!0});return{builder:(0,instructions_1.launchProposal)(this.program,e,t,a.vault,i,s,h).preInstructions(this.maybeAddComputeBudget(r))}}async ensureConditionalATAs(e,t){const i=await this.fetchProposal(t),s=await this.vault.fetchVault(i.vault),r=s.condBaseMints.slice(0,i.numOptions),a=s.condQuoteMints.slice(0,i.numOptions);return this._createConditionalATAs(e,r,a)}async _createConditionalATAs(e,t,i){const s=this.program.provider,r=[];for(let s=0;s<t.length;s++){const a=(0,spl_token_1.getAssociatedTokenAddressSync)(t[s],e),o=(0,spl_token_1.getAssociatedTokenAddressSync)(i[s],e);r.push((0,spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(e,a,e,t[s]),(0,spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(e,o,e,i[s]))}const a=(new web3_js_1.Transaction).add(...r);return s.sendAndConfirm(a)}async finalizeProposal(e,t,i){const s=await this.fetchProposal(t),r=await this.vault.fetchVault(s.vault),a=s.numOptions,o=[];for(let e=0;e<a;e++){const t=s.pools[e],[i]=(0,amm_1.deriveReservePDA)(t,r.condQuoteMints[e],this.amm.programId),[a]=(0,amm_1.deriveReservePDA)(t,r.condBaseMints[e],this.amm.programId);o.push({pubkey:t,isSigner:!1,isWritable:!0}),o.push({pubkey:i,isSigner:!1,isWritable:!1}),o.push({pubkey:a,isSigner:!1,isWritable:!1})}return{builder:(0,instructions_1.finalizeProposal)(this.program,e,t,s.vault,o).preInstructions(this.maybeAddComputeBudget(i))}}async redeemLiquidity(e,t,i){const s=await this.fetchProposal(t),r=await this.vault.fetchVault(s.vault),a=s.numOptions,{winningIdx:o}=(0,utils_1.parseProposalState)(s.state);if(null===o)throw new Error("Proposal not finalized");const n=s.pools[o],[d]=(0,amm_1.deriveReservePDA)(n,r.condQuoteMints[o],this.amm.programId),[l]=(0,amm_1.deriveReservePDA)(n,r.condBaseMints[o],this.amm.programId),u=[{pubkey:d,isSigner:!1,isWritable:!0},{pubkey:l,isSigner:!1,isWritable:!0},{pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(r.condQuoteMints[o],e),isSigner:!1,isWritable:!0},{pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(r.condBaseMints[o],e),isSigner:!1,isWritable:!0},{pubkey:r.baseMint.address,isSigner:!1,isWritable:!1},{pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(r.baseMint.address,s.vault,!0),isSigner:!1,isWritable:!0},{pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(r.baseMint.address,e),isSigner:!1,isWritable:!0}];for(let t=0;t<a;t++)u.push({pubkey:r.condBaseMints[t],isSigner:!1,isWritable:!0}),u.push({pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(r.condBaseMints[t],e),isSigner:!1,isWritable:!0});u.push({pubkey:r.quoteMint.address,isSigner:!1,isWritable:!1}),u.push({pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(r.quoteMint.address,s.vault,!0),isSigner:!1,isWritable:!0}),u.push({pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(r.quoteMint.address,e),isSigner:!1,isWritable:!0});for(let t=0;t<a;t++)u.push({pubkey:r.condQuoteMints[t],isSigner:!1,isWritable:!0}),u.push({pubkey:(0,spl_token_1.getAssociatedTokenAddressSync)(r.condQuoteMints[t],e),isSigner:!1,isWritable:!0});return{builder:(0,instructions_1.redeemLiquidity)(this.program,e,t,s.vault,n,u).preInstructions(this.maybeAddComputeBudget(i)),numOptions:a}}async createRedemptionALT(e,t){const i=this.program.provider,s=await this.fetchProposal(t),r=await this.vault.fetchVault(s.vault),a=s.numOptions,{winningIdx:o}=(0,utils_1.parseProposalState)(s.state);if(null===o)throw new Error("Proposal not finalized");const n=[this.programId,this.vault.programId,this.amm.programId,web3_js_1.SystemProgram.programId,spl_token_1.TOKEN_PROGRAM_ID,spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,t,s.vault,s.moderator,r.baseMint.address,r.quoteMint.address,s.pools[o],(0,spl_token_1.getAssociatedTokenAddressSync)(r.baseMint.address,s.vault,!0),(0,spl_token_1.getAssociatedTokenAddressSync)(r.quoteMint.address,s.vault,!0),(0,spl_token_1.getAssociatedTokenAddressSync)(r.baseMint.address,e),(0,spl_token_1.getAssociatedTokenAddressSync)(r.quoteMint.address,e)],[d]=(0,amm_1.deriveReservePDA)(s.pools[o],r.condQuoteMints[o],this.amm.programId),[l]=(0,amm_1.deriveReservePDA)(s.pools[o],r.condBaseMints[o],this.amm.programId);n.push(d,l);for(let t=0;t<a;t++)n.push(r.condBaseMints[t],r.condQuoteMints[t],(0,spl_token_1.getAssociatedTokenAddressSync)(r.condBaseMints[t],e),(0,spl_token_1.getAssociatedTokenAddressSync)(r.condQuoteMints[t],e));const u=await i.connection.getSlot("finalized"),[c,p]=web3_js_1.AddressLookupTableProgram.createLookupTable({authority:e,payer:e,recentSlot:u}),m=(new web3_js_1.Transaction).add(c),{blockhash:g,lastValidBlockHeight:h}=await i.connection.getLatestBlockhash("confirmed");m.recentBlockhash=g,m.feePayer=e;const _=await i.wallet.signTransaction(m),b=await i.connection.sendRawTransaction(_.serialize(),{skipPreflight:!0});await i.connection.confirmTransaction({signature:b,blockhash:g,lastValidBlockHeight:h},"confirmed");for(let t=0;t<n.length;t+=20){const s=n.slice(t,t+20),r=web3_js_1.AddressLookupTableProgram.extendLookupTable({payer:e,authority:e,lookupTable:p,addresses:s}),a=(new web3_js_1.Transaction).add(r),{blockhash:o,lastValidBlockHeight:d}=await i.connection.getLatestBlockhash("confirmed");a.recentBlockhash=o,a.feePayer=e;const l=await i.wallet.signTransaction(a),u=await i.connection.sendRawTransaction(l.serialize(),{skipPreflight:!0});await i.connection.confirmTransaction({signature:u,blockhash:o,lastValidBlockHeight:d},"confirmed")}return{altAddress:p}}async redeemLiquidityVersioned(e,t,i,s){const r=this.program.provider,{builder:a,numOptions:o}=await this.redeemLiquidity(e,t);let n=i,d=null;if(!n&&o>=3){console.log(` Creating redemption ALT for ${o} options...`);n=(await this.createRedemptionALT(e,t)).altAddress,console.log(` ✓ Redemption ALT created: ${n.toBase58()}`),console.log(" Waiting for ALT propagation...");const i=18+4*o;let s=0;for(await new Promise(e=>setTimeout(e,2e3));s<30;){const e=await r.connection.getAddressLookupTable(n,{commitment:"confirmed"});if(e.value){const t=e.value.state.addresses.length;if(console.log(` Attempt ${s+1}: ALT has ${t}/${i} addresses`),t>=i){d=e.value,console.log(` ✓ ALT verified with ${t} addresses`);break}}await new Promise(e=>setTimeout(e,1e3)),s++}if(!d)throw new Error(`ALT failed to populate with expected ${i} addresses after ${s} attempts`)}if(!n)throw new Error("ALT address required for multi-option redemption");d||(d=await this.fetchALT(n));const l=await a.instruction(),u=[web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({units:5e5})];void 0!==s?.priorityFeeMicroLamports&&s.priorityFeeMicroLamports>0&&u.push(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({microLamports:s.priorityFeeMicroLamports}));const{blockhash:c,lastValidBlockHeight:p}=await r.connection.getLatestBlockhash("confirmed");return{versionedTx:this.buildVersionedTxWithALT(e,[...u,l],d,c),altAddress:n,numOptions:o,blockhash:c,lastValidBlockHeight:p}}async sendVersionedTransaction(e,t){const i=this.program.provider;let s,r;if(t)s=t.blockhash,r=t.lastValidBlockHeight;else{const e=await i.connection.getLatestBlockhash("confirmed");s=e.blockhash,r=e.lastValidBlockHeight}const a=await i.connection.sendTransaction(e,{skipPreflight:!1,preflightCommitment:"confirmed"});return await i.connection.confirmTransaction({signature:a,blockhash:s,lastValidBlockHeight:r},"confirmed"),a}async createProposalALT(e,t,i=2){const s=this.program.provider,r=await this.fetchModerator(t),a=r.proposalIdCounter,[o]=this.deriveProposalPDA(t,a),[n]=(0,vault_1.deriveVaultPDA)(o,a,this.vault.programId),d=[this.programId,this.vault.programId,this.amm.programId,web3_js_1.SystemProgram.programId,spl_token_1.TOKEN_PROGRAM_ID,spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,t,o,n,r.baseMint,r.quoteMint,amm_1.FEE_AUTHORITY,(0,spl_token_1.getAssociatedTokenAddressSync)(r.baseMint,n,!0),(0,spl_token_1.getAssociatedTokenAddressSync)(r.quoteMint,n,!0),(0,spl_token_1.getAssociatedTokenAddressSync)(r.baseMint,e),(0,spl_token_1.getAssociatedTokenAddressSync)(r.quoteMint,e)];for(let t=0;t<i;t++){const[i]=(0,vault_1.deriveConditionalMint)(n,vault_1.VaultType.Base,t,this.vault.programId),[s]=(0,vault_1.deriveConditionalMint)(n,vault_1.VaultType.Quote,t,this.vault.programId),[r]=(0,amm_1.derivePoolPDA)(o,s,i,this.amm.programId),[a]=(0,amm_1.deriveReservePDA)(r,s,this.amm.programId),[l]=(0,amm_1.deriveReservePDA)(r,i,this.amm.programId),[u]=(0,amm_1.deriveFeeVaultPDA)(r,this.amm.programId);d.push(i,s,r,a,l,u,(0,spl_token_1.getAssociatedTokenAddressSync)(i,e),(0,spl_token_1.getAssociatedTokenAddressSync)(s,e))}const l=await s.connection.getSlot("finalized"),[u,c]=web3_js_1.AddressLookupTableProgram.createLookupTable({authority:e,payer:e,recentSlot:l}),p=(new web3_js_1.Transaction).add(u),{blockhash:m,lastValidBlockHeight:g}=await s.connection.getLatestBlockhash("confirmed");p.recentBlockhash=m,p.feePayer=e;const h=await s.wallet.signTransaction(p),_=await s.connection.sendRawTransaction(h.serialize(),{skipPreflight:!0});await s.connection.confirmTransaction({signature:_,blockhash:m,lastValidBlockHeight:g},"confirmed");for(let t=0;t<d.length;t+=20){const i=d.slice(t,t+20),r=web3_js_1.AddressLookupTableProgram.extendLookupTable({payer:e,authority:e,lookupTable:c,addresses:i}),a=(new web3_js_1.Transaction).add(r),{blockhash:o,lastValidBlockHeight:n}=await s.connection.getLatestBlockhash("confirmed");a.recentBlockhash=o,a.feePayer=e;const l=await s.wallet.signTransaction(a),u=await s.connection.sendRawTransaction(l.serialize(),{skipPreflight:!0});await s.connection.confirmTransaction({signature:u,blockhash:o,lastValidBlockHeight:n},"confirmed")}return{altAddress:c}}async fetchALT(e){const t=await this.program.provider.connection.getAddressLookupTable(e);if(!t.value)throw new Error("ALT not found");return t.value}async buildVersionedTx(e,t,i){const s=this.program.provider,r=await this.fetchALT(i),{blockhash:a,lastValidBlockHeight:o}=await s.connection.getLatestBlockhash("confirmed");return{versionedTx:this.buildVersionedTxWithALT(e,t,r,a),blockhash:a,lastValidBlockHeight:o}}buildVersionedTxWithALT(e,t,i,s){const r=new web3_js_1.TransactionMessage({payerKey:e,recentBlockhash:s,instructions:t}).compileToV0Message([i]);return new web3_js_1.VersionedTransaction(r)}deriveMintCreateKeyPDA(e,t){return(0,utils_1.deriveMintCreateKeyPDA)(e,t,this.programId)}async fetchSquadsProgramConfig(){const[e]=multisig.getProgramConfigPda({programId:constants_1.SQUADS_PROGRAM_ID});return{programConfig:e,programConfigTreasury:(await multisig.accounts.ProgramConfig.fromAccountAddress(this.program.provider.connection,e)).treasury}}deriveMultisigPda(e){const[t]=multisig.getMultisigPda({createKey:e,programId:constants_1.SQUADS_PROGRAM_ID});return t}async initializeParentDAO(e,t,i,s,r,a,o,n,d){const[l]=this.deriveDAOPDA(i),[u]=this.deriveModeratorPDA(i),[c]=this.deriveMintCreateKeyPDA(l,i),p=await this.fetchSquadsProgramConfig(),m=this.deriveMultisigPda(l),g=this.deriveMultisigPda(c);return{builder:(0,instructions_1.initializeParentDAO)(this.program,e,t,l,u,s,r,p.programConfig,p.programConfigTreasury,m,g,c,constants_1.SQUADS_PROGRAM_ID,i,a,o,n).preInstructions(this.maybeAddComputeBudget(d)),daoPda:l,moderatorPda:u,treasuryMultisig:m,mintMultisig:g}}async initializeChildDAO(e,t,i,s,r,a,o){const[n]=this.deriveDAOPDA(s),[d]=this.deriveDAOPDA(i),[l]=this.deriveMintCreateKeyPDA(n,s),u=await this.fetchSquadsProgramConfig(),c=this.deriveMultisigPda(n),p=this.deriveMultisigPda(l);return{builder:(0,instructions_1.initializeChildDAO)(this.program,e,t,n,d,r,u.programConfig,u.programConfigTreasury,c,p,l,constants_1.SQUADS_PROGRAM_ID,s,a).preInstructions(this.maybeAddComputeBudget(o)),daoPda:n,parentDaoPda:d,treasuryMultisig:c,mintMultisig:p}}async upgradeDAO(e,t,i,s,r,a,o,n,d){const[l]=this.deriveDAOPDA(i),[u]=this.deriveDAOPDA(s),[c]=this.deriveModeratorPDA(i);return{builder:(0,instructions_1.upgradeDAO)(this.program,e,t,l,u,c,r,a,o,n).preInstructions(this.maybeAddComputeBudget(d)),daoPda:l,moderatorPda:c}}async addHistoricalParentDAO(e,t,i,s,r,a,o,n,d,l,u,c){const[p]=this.deriveDAOPDA(t),[m]=this.deriveModeratorPDA(t);return{builder:(0,instructions_1.addHistoricalParentDAO)(this.program,e,p,m,r,a,i,s,t,o,n,d,l,u).preInstructions(this.maybeAddComputeBudget(c)),daoPda:p,moderatorPda:m}}async transferAdmin(e,t,i,s){const[r]=this.deriveDAOPDA(t),[a]=this.deriveModeratorPDA(t);return{builder:(0,instructions_1.transferAdmin)(this.program,e,r,a,i).preInstructions(this.maybeAddComputeBudget(s)),daoPda:r,moderatorPda:a}}}exports.FutarchyClient=FutarchyClient;