@baozi.bet/mcp-server 4.0.0

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.
Files changed (60) hide show
  1. package/README.md +294 -0
  2. package/dist/__tests__/full-test.d.ts +1 -0
  3. package/dist/__tests__/full-test.js +291 -0
  4. package/dist/builders/affiliate-transaction.d.ts +41 -0
  5. package/dist/builders/affiliate-transaction.js +123 -0
  6. package/dist/builders/bet-transaction.d.ts +70 -0
  7. package/dist/builders/bet-transaction.js +323 -0
  8. package/dist/builders/claim-transaction.d.ts +57 -0
  9. package/dist/builders/claim-transaction.js +196 -0
  10. package/dist/builders/creator-transaction.d.ts +49 -0
  11. package/dist/builders/creator-transaction.js +177 -0
  12. package/dist/builders/dispute-transaction.d.ts +81 -0
  13. package/dist/builders/dispute-transaction.js +215 -0
  14. package/dist/builders/index.d.ts +14 -0
  15. package/dist/builders/index.js +15 -0
  16. package/dist/builders/market-creation-tx.d.ts +65 -0
  17. package/dist/builders/market-creation-tx.js +362 -0
  18. package/dist/builders/market-management-transaction.d.ts +85 -0
  19. package/dist/builders/market-management-transaction.js +239 -0
  20. package/dist/builders/race-transaction.d.ts +67 -0
  21. package/dist/builders/race-transaction.js +242 -0
  22. package/dist/builders/resolution-transaction.d.ts +108 -0
  23. package/dist/builders/resolution-transaction.js +250 -0
  24. package/dist/builders/whitelist-transaction.d.ts +72 -0
  25. package/dist/builders/whitelist-transaction.js +179 -0
  26. package/dist/config.d.ts +138 -0
  27. package/dist/config.js +307 -0
  28. package/dist/handlers/agent-network.d.ts +81 -0
  29. package/dist/handlers/agent-network.js +332 -0
  30. package/dist/handlers/claims.d.ts +47 -0
  31. package/dist/handlers/claims.js +218 -0
  32. package/dist/handlers/market-creation.d.ts +154 -0
  33. package/dist/handlers/market-creation.js +290 -0
  34. package/dist/handlers/markets.d.ts +41 -0
  35. package/dist/handlers/markets.js +319 -0
  36. package/dist/handlers/positions.d.ts +40 -0
  37. package/dist/handlers/positions.js +244 -0
  38. package/dist/handlers/quote.d.ts +33 -0
  39. package/dist/handlers/quote.js +144 -0
  40. package/dist/handlers/race-markets.d.ts +54 -0
  41. package/dist/handlers/race-markets.js +308 -0
  42. package/dist/handlers/resolution.d.ts +43 -0
  43. package/dist/handlers/resolution.js +194 -0
  44. package/dist/index.d.ts +2 -0
  45. package/dist/index.js +109 -0
  46. package/dist/resources.d.ts +13 -0
  47. package/dist/resources.js +336 -0
  48. package/dist/tools.d.ts +3109 -0
  49. package/dist/tools.js +1956 -0
  50. package/dist/validation/bet-rules.d.ts +82 -0
  51. package/dist/validation/bet-rules.js +276 -0
  52. package/dist/validation/creation-rules.d.ts +69 -0
  53. package/dist/validation/creation-rules.js +302 -0
  54. package/dist/validation/index.d.ts +6 -0
  55. package/dist/validation/index.js +7 -0
  56. package/dist/validation/market-rules.d.ts +60 -0
  57. package/dist/validation/market-rules.js +237 -0
  58. package/dist/validation/parimutuel-rules.d.ts +117 -0
  59. package/dist/validation/parimutuel-rules.js +270 -0
  60. package/package.json +52 -0
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Bet Validation Rules
3
+ *
4
+ * Validates bet parameters against protocol constraints:
5
+ * - Amount limits (0.01-100 SOL)
6
+ * - Market state (active, not frozen, not paused)
7
+ * - Whitelist access (for private markets)
8
+ * - Timing constraints (betting freeze)
9
+ */
10
+ export interface BetValidationParams {
11
+ amountSol: number;
12
+ marketStatus: number;
13
+ closingTime: Date;
14
+ isPaused: boolean;
15
+ accessGate: number;
16
+ userWhitelisted?: boolean;
17
+ layer?: number;
18
+ }
19
+ export interface BetValidation {
20
+ valid: boolean;
21
+ error?: string;
22
+ warnings: string[];
23
+ details: {
24
+ amountValid: boolean;
25
+ marketStateValid: boolean;
26
+ timingValid: boolean;
27
+ accessValid: boolean;
28
+ };
29
+ }
30
+ export interface ClaimValidationParams {
31
+ marketStatus: number;
32
+ marketOutcome: number;
33
+ positionSide: 'Yes' | 'No';
34
+ positionAmount: number;
35
+ alreadyClaimed: boolean;
36
+ }
37
+ export interface ClaimValidation {
38
+ valid: boolean;
39
+ error?: string;
40
+ canClaim: boolean;
41
+ isWinner: boolean;
42
+ }
43
+ /**
44
+ * Validate bet parameters before building transaction
45
+ */
46
+ export declare function validateBet(params: BetValidationParams): BetValidation;
47
+ /**
48
+ * Validate claim parameters before building claim transaction
49
+ */
50
+ export declare function validateClaim(params: ClaimValidationParams): ClaimValidation;
51
+ /**
52
+ * Calculate quote for a bet (pari-mutuel)
53
+ */
54
+ export declare function calculateBetQuote(params: {
55
+ betAmountSol: number;
56
+ side: 'Yes' | 'No';
57
+ currentYesPool: number;
58
+ currentNoPool: number;
59
+ platformFeeBps: number;
60
+ }): {
61
+ expectedPayoutSol: number;
62
+ potentialProfitSol: number;
63
+ feeSol: number;
64
+ impliedOdds: number;
65
+ decimalOdds: number;
66
+ newYesPool: number;
67
+ newNoPool: number;
68
+ };
69
+ /**
70
+ * Estimate claim amount for a winning position
71
+ */
72
+ export declare function estimateClaimAmount(params: {
73
+ positionAmount: number;
74
+ positionSide: 'Yes' | 'No';
75
+ totalYesPool: number;
76
+ totalNoPool: number;
77
+ platformFeeBps: number;
78
+ }): {
79
+ grossPayout: number;
80
+ fee: number;
81
+ netPayout: number;
82
+ };
@@ -0,0 +1,276 @@
1
+ /**
2
+ * Bet Validation Rules
3
+ *
4
+ * Validates bet parameters against protocol constraints:
5
+ * - Amount limits (0.01-100 SOL)
6
+ * - Market state (active, not frozen, not paused)
7
+ * - Whitelist access (for private markets)
8
+ * - Timing constraints (betting freeze)
9
+ */
10
+ import { BET_LIMITS, TIMING, MARKET_STATUS, ACCESS_GATE, MARKET_LAYER_NAMES, } from '../config.js';
11
+ // =============================================================================
12
+ // BET VALIDATION
13
+ // =============================================================================
14
+ /**
15
+ * Validate bet parameters before building transaction
16
+ */
17
+ export function validateBet(params) {
18
+ const warnings = [];
19
+ const details = {
20
+ amountValid: true,
21
+ marketStateValid: true,
22
+ timingValid: true,
23
+ accessValid: true,
24
+ };
25
+ // ==========================================================================
26
+ // Amount Validation
27
+ // ==========================================================================
28
+ if (params.amountSol < BET_LIMITS.MIN_BET_SOL) {
29
+ details.amountValid = false;
30
+ return {
31
+ valid: false,
32
+ error: `Minimum bet is ${BET_LIMITS.MIN_BET_SOL} SOL`,
33
+ warnings,
34
+ details,
35
+ };
36
+ }
37
+ if (params.amountSol > BET_LIMITS.MAX_BET_SOL) {
38
+ details.amountValid = false;
39
+ return {
40
+ valid: false,
41
+ error: `Maximum bet is ${BET_LIMITS.MAX_BET_SOL} SOL`,
42
+ warnings,
43
+ details,
44
+ };
45
+ }
46
+ // Amount warnings
47
+ if (params.amountSol > 50) {
48
+ warnings.push('Large bet amount. Ensure you understand the odds before placing.');
49
+ }
50
+ // ==========================================================================
51
+ // Market State Validation
52
+ // ==========================================================================
53
+ if (params.marketStatus !== MARKET_STATUS.ACTIVE) {
54
+ details.marketStateValid = false;
55
+ const statusName = getStatusName(params.marketStatus);
56
+ return {
57
+ valid: false,
58
+ error: `Market is ${statusName}, not accepting bets`,
59
+ warnings,
60
+ details,
61
+ };
62
+ }
63
+ if (params.isPaused) {
64
+ details.marketStateValid = false;
65
+ return {
66
+ valid: false,
67
+ error: 'Market is paused',
68
+ warnings,
69
+ details,
70
+ };
71
+ }
72
+ // ==========================================================================
73
+ // Timing Validation
74
+ // ==========================================================================
75
+ const now = new Date();
76
+ const freezeTime = new Date(params.closingTime.getTime() - TIMING.BETTING_FREEZE_SECONDS * 1000);
77
+ if (now >= params.closingTime) {
78
+ details.timingValid = false;
79
+ return {
80
+ valid: false,
81
+ error: 'Betting has closed',
82
+ warnings,
83
+ details,
84
+ };
85
+ }
86
+ if (now >= freezeTime) {
87
+ details.timingValid = false;
88
+ const remainingMs = params.closingTime.getTime() - now.getTime();
89
+ const remainingMin = Math.ceil(remainingMs / 60000);
90
+ return {
91
+ valid: false,
92
+ error: `Betting is frozen (${remainingMin} minutes until close)`,
93
+ warnings,
94
+ details,
95
+ };
96
+ }
97
+ // Timing warnings
98
+ const timeToFreezeMs = freezeTime.getTime() - now.getTime();
99
+ const timeToFreezeMin = Math.floor(timeToFreezeMs / 60000);
100
+ if (timeToFreezeMin < 30) {
101
+ warnings.push(`Betting freezes in ${timeToFreezeMin} minutes`);
102
+ }
103
+ // ==========================================================================
104
+ // Access Validation (Whitelist)
105
+ // ==========================================================================
106
+ if (params.accessGate === ACCESS_GATE.WHITELIST) {
107
+ if (params.userWhitelisted !== true) {
108
+ details.accessValid = false;
109
+ return {
110
+ valid: false,
111
+ error: 'You are not whitelisted for this private market',
112
+ warnings,
113
+ details,
114
+ };
115
+ }
116
+ }
117
+ // Layer-specific warnings
118
+ if (params.layer !== undefined) {
119
+ const layerName = MARKET_LAYER_NAMES[params.layer] || 'Unknown';
120
+ if (params.layer === 1) { // Lab
121
+ warnings.push(`This is a ${layerName} market (community-created). DYOR.`);
122
+ }
123
+ }
124
+ return {
125
+ valid: true,
126
+ warnings,
127
+ details,
128
+ };
129
+ }
130
+ // =============================================================================
131
+ // CLAIM VALIDATION
132
+ // =============================================================================
133
+ /**
134
+ * Validate claim parameters before building claim transaction
135
+ */
136
+ export function validateClaim(params) {
137
+ // Already claimed
138
+ if (params.alreadyClaimed) {
139
+ return {
140
+ valid: false,
141
+ error: 'Position already claimed',
142
+ canClaim: false,
143
+ isWinner: false,
144
+ };
145
+ }
146
+ // Market not resolved
147
+ if (params.marketStatus !== MARKET_STATUS.RESOLVED &&
148
+ params.marketStatus !== MARKET_STATUS.CANCELLED) {
149
+ const statusName = getStatusName(params.marketStatus);
150
+ return {
151
+ valid: false,
152
+ error: `Market is ${statusName}, cannot claim yet`,
153
+ canClaim: false,
154
+ isWinner: false,
155
+ };
156
+ }
157
+ // Cancelled market - everyone can claim refund
158
+ if (params.marketStatus === MARKET_STATUS.CANCELLED) {
159
+ return {
160
+ valid: true,
161
+ canClaim: true,
162
+ isWinner: false, // Refund, not winning
163
+ };
164
+ }
165
+ // Check if position is on winning side
166
+ const isWinner = (params.positionSide === 'Yes' && params.marketOutcome === 2) ||
167
+ (params.positionSide === 'No' && params.marketOutcome === 3);
168
+ if (!isWinner) {
169
+ return {
170
+ valid: false,
171
+ error: 'Position is on losing side, nothing to claim',
172
+ canClaim: false,
173
+ isWinner: false,
174
+ };
175
+ }
176
+ // Nothing to claim if amount is 0
177
+ if (params.positionAmount <= 0) {
178
+ return {
179
+ valid: false,
180
+ error: 'No position amount to claim',
181
+ canClaim: false,
182
+ isWinner: true,
183
+ };
184
+ }
185
+ return {
186
+ valid: true,
187
+ canClaim: true,
188
+ isWinner: true,
189
+ };
190
+ }
191
+ // =============================================================================
192
+ // HELPER FUNCTIONS
193
+ // =============================================================================
194
+ function getStatusName(status) {
195
+ switch (status) {
196
+ case MARKET_STATUS.ACTIVE: return 'Active';
197
+ case MARKET_STATUS.CLOSED: return 'Closed';
198
+ case MARKET_STATUS.RESOLVED: return 'Resolved';
199
+ case MARKET_STATUS.CANCELLED: return 'Cancelled';
200
+ case MARKET_STATUS.PAUSED: return 'Paused';
201
+ case MARKET_STATUS.RESOLVED_PENDING: return 'Pending Resolution';
202
+ case MARKET_STATUS.DISPUTED: return 'Disputed';
203
+ default: return 'Unknown';
204
+ }
205
+ }
206
+ /**
207
+ * Calculate quote for a bet (pari-mutuel)
208
+ */
209
+ export function calculateBetQuote(params) {
210
+ // Calculate new pools after bet
211
+ const newYesPool = params.side === 'Yes'
212
+ ? params.currentYesPool + params.betAmountSol
213
+ : params.currentYesPool;
214
+ const newNoPool = params.side === 'No'
215
+ ? params.currentNoPool + params.betAmountSol
216
+ : params.currentNoPool;
217
+ const newTotalPool = newYesPool + newNoPool;
218
+ // Calculate expected payout (pari-mutuel)
219
+ const sidePool = params.side === 'Yes' ? newYesPool : newNoPool;
220
+ const expectedPayoutSol = sidePool > 0
221
+ ? (params.betAmountSol / sidePool) * newTotalPool
222
+ : 0;
223
+ // Calculate profit and fee
224
+ const grossProfit = expectedPayoutSol - params.betAmountSol;
225
+ const feeSol = grossProfit > 0
226
+ ? (grossProfit * params.platformFeeBps) / 10000
227
+ : 0;
228
+ const potentialProfitSol = grossProfit - feeSol;
229
+ // Calculate odds
230
+ const impliedOdds = newTotalPool > 0
231
+ ? (sidePool / newTotalPool) * 100
232
+ : 50;
233
+ const decimalOdds = sidePool > 0
234
+ ? newTotalPool / sidePool
235
+ : 2;
236
+ return {
237
+ expectedPayoutSol: round4(expectedPayoutSol),
238
+ potentialProfitSol: round4(potentialProfitSol),
239
+ feeSol: round4(feeSol),
240
+ impliedOdds: round2(impliedOdds),
241
+ decimalOdds: round2(decimalOdds),
242
+ newYesPool: round4(newYesPool),
243
+ newNoPool: round4(newNoPool),
244
+ };
245
+ }
246
+ /**
247
+ * Estimate claim amount for a winning position
248
+ */
249
+ export function estimateClaimAmount(params) {
250
+ const totalPool = params.totalYesPool + params.totalNoPool;
251
+ const winningPool = params.positionSide === 'Yes'
252
+ ? params.totalYesPool
253
+ : params.totalNoPool;
254
+ // Calculate share of winning pool
255
+ const shareOfPool = winningPool > 0
256
+ ? params.positionAmount / winningPool
257
+ : 0;
258
+ // Gross payout from total pool
259
+ const grossPayout = shareOfPool * totalPool;
260
+ // Calculate fee on profit only
261
+ const profit = grossPayout - params.positionAmount;
262
+ const fee = profit > 0 ? (profit * params.platformFeeBps) / 10000 : 0;
263
+ return {
264
+ grossPayout: round4(grossPayout),
265
+ fee: round4(fee),
266
+ netPayout: round4(grossPayout - fee),
267
+ };
268
+ }
269
+ // Rounding helpers
270
+ function round2(n) {
271
+ return Math.round(n * 100) / 100;
272
+ }
273
+ function round4(n) {
274
+ return Math.round(n * 10000) / 10000;
275
+ }
276
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmV0LXJ1bGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3ZhbGlkYXRpb24vYmV0LXJ1bGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBRUgsT0FBTyxFQUNMLFVBQVUsRUFDVixNQUFNLEVBQ04sYUFBYSxFQUNiLFdBQVcsRUFDWCxrQkFBa0IsR0FDbkIsTUFBTSxjQUFjLENBQUM7QUEyQ3RCLGdGQUFnRjtBQUNoRixpQkFBaUI7QUFDakIsZ0ZBQWdGO0FBRWhGOztHQUVHO0FBQ0gsTUFBTSxVQUFVLFdBQVcsQ0FBQyxNQUEyQjtJQUNyRCxNQUFNLFFBQVEsR0FBYSxFQUFFLENBQUM7SUFDOUIsTUFBTSxPQUFPLEdBQUc7UUFDZCxXQUFXLEVBQUUsSUFBSTtRQUNqQixnQkFBZ0IsRUFBRSxJQUFJO1FBQ3RCLFdBQVcsRUFBRSxJQUFJO1FBQ2pCLFdBQVcsRUFBRSxJQUFJO0tBQ2xCLENBQUM7SUFFRiw2RUFBNkU7SUFDN0Usb0JBQW9CO0lBQ3BCLDZFQUE2RTtJQUM3RSxJQUFJLE1BQU0sQ0FBQyxTQUFTLEdBQUcsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzlDLE9BQU8sQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO1FBQzVCLE9BQU87WUFDTCxLQUFLLEVBQUUsS0FBSztZQUNaLEtBQUssRUFBRSxrQkFBa0IsVUFBVSxDQUFDLFdBQVcsTUFBTTtZQUNyRCxRQUFRO1lBQ1IsT0FBTztTQUNSLENBQUM7SUFDSixDQUFDO0lBRUQsSUFBSSxNQUFNLENBQUMsU0FBUyxHQUFHLFVBQVUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUM5QyxPQUFPLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQztRQUM1QixPQUFPO1lBQ0wsS0FBSyxFQUFFLEtBQUs7WUFDWixLQUFLLEVBQUUsa0JBQWtCLFVBQVUsQ0FBQyxXQUFXLE1BQU07WUFDckQsUUFBUTtZQUNSLE9BQU87U0FDUixDQUFDO0lBQ0osQ0FB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LENBQUMsQ0FBQyxNQUFNLENBQUMsWUFBWTtRQUNyQixDQUFDLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQztJQUV2QixrQ0FBa0M7SUFDbEMsTUFBTSxXQUFXLEdBQUcsV0FBVyxHQUFHLENBQUM7UUFDakMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxjQUFjLEdBQUcsV0FBVztRQUNyQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRU4sK0JBQStCO0lBQy9CLE1BQU0sV0FBVyxHQUFHLFdBQVcsR0FBRyxTQUFTLENBQUM7SUFFNUMsK0JBQStCO0lBQy9CLE1BQU0sTUFBTSxHQUFHLFdBQVcsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDO0lBQ25ELE1BQU0sR0FBRyxHQUFHLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUV0RSxPQUFPO1FBQ0wsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXLENBQUM7UUFDaEMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUM7UUFDaEIsU0FBUyxFQUFFLE1BQU0sQ0FBQyxXQUFXLEdBQUcsR0FBRyxDQUFDO0tBQ3JDLENBQUM7QUFDSixDQUFDO0FBRUQsbUJBQW1CO0FBQ25CLFNBQVMsTUFBTSxDQUFDLENBQVM7SUFDdkIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUM7QUFDbkMsQ0FBQztBQUVELFNBQVMsTUFBTSxDQUFDLENBQVM7SUFDdkIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUM7QUFDdkMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQmV0IFZhbGlkYXRpb24gUnVsZXNcbiAqXG4gKiBWYWxpZGF0ZXMgYmV0IHBhcmFtZXRlcnMgYWdhaW5zdCBwcm90b2NvbCBjb25zdHJhaW50czpcbiAqIC0gQW1vdW50IGxpbWl0cyAoMC4wMS0xMDAgU09MKVxuICogLSBNYXJrZXQgc3RhdGUgKGFjdGl2ZSwgbm90IGZyb3plbiwgbm90IHBhdXNlZClcbiAqIC0gV2hpdGVsaXN0IGFjY2VzcyAoZm9yIHByaXZhdGUgbWFya2V0cylcbiAqIC0gVGltaW5nIGNvbnN0cmFpbnRzIChiZXR0aW5nIGZyZWV6ZSlcbiAqL1xuXG5pbXBvcnQge1xuICBCRVRfTElNSVRTLFxuICBUSU1JTkcsXG4gIE1BUktFVF9TVEFUVVMsXG4gIEFDQ0VTU19HQVRFLFxuICBNQVJLRVRfTEFZRVJfTkFNRVMsXG59IGZyb20gJy4uL2NvbmZpZy5qcyc7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBCZXRWYWxpZGF0aW9uUGFyYW1zIHtcbiAgYW1vdW50U29sOiBudW1iZXI7XG4gIG1hcmtldFN0YXR1czogbnVtYmVyO1xuICBjbG9zaW5nVGltZTogRGF0ZTtcbiAgaXNQYXVzZWQ6IGJvb2xlYW47XG4gIGFjY2Vzc0dhdGU6IG51bWJlcjtcbiAgdXNlcldoaXRlbGlzdGVkPzogYm9vbGVhbjtcbiAgbGF5ZXI/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQmV0VmFsaWRhdGlvbiB7XG4gIHZhbGlkOiBib29sZWFuO1xuICBlcnJvcj86IHN0cmluZztcbiAgd2FybmluZ3M6IHN0cmluZ1tdO1xuICBkZXRhaWxzOiB7XG4gICAgYW1vdW50VmFsaWQ6IGJvb2xlYW47XG4gICAgbWFya2V0U3RhdGVWYWxpZDogYm9vbGVhbjtcbiAgICB0aW1pbmdWYWxpZDogYm9vbGVhbjtcbiAgICBhY2Nlc3NWYWxpZDogYm9vbGVhbjtcbiAgfTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDbGFpbVZhbGlkYXRpb25QYXJhbXMge1xuICBtYXJrZXRTdGF0dXM6IG51bWJlcjtcbiAgbWFya2V0T3V0Y29tZTogbnVtYmVyO1xuICBwb3NpdGlvblNpZGU6ICdZZXMnIHwgJ05vJztcbiAgcG9zaXRpb25BbW91bnQ6IG51bWJlcjtcbiAgYWxyZWFkeUNsYWltZWQ6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xhaW1WYWxpZGF0aW9uIHtcbiAgdmFsaWQ6IGJvb2xlYW47XG4gIGVycm9yPzogc3RyaW5nO1xuICBjYW5DbGFpbTogYm9vbGVhbjtcbiAgaXNXaW5uZXI6IGJvb2xlYW47XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBCRVQgVkFMSURBVElPTlxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBWYWxpZGF0ZSBiZXQgcGFyYW1ldGVycyBiZWZvcmUgYnVpbGRpbmcgdHJhbnNhY3Rpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlQmV0KHBhcmFtczogQmV0VmFsaWRhdGlvblBhcmFtcyk6IEJldFZhbGlkYXRpb24ge1xuICBjb25zdCB3YXJuaW5nczogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgZGV0YWlscyA9IHtcbiAgICBhbW91bnRWYWxpZDogdHJ1ZSxcbiAgICBtYXJrZXRTdGF0ZVZhbGlkOiB0cnVlLFxuICAgIHRpbWluZ1ZhbGlkOiB0cnVlLFxuICAgIGFjY2Vzc1ZhbGlkOiB0cnVlLFxuICB9O1xuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIEFtb3VudCBWYWxpZGF0aW9uXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIGlmIChwYXJhbXMuYW1vdW50U29sIDwgQkVUX0xJTUlUUy5NSU5fQkVUX1NPTCkge1xuICAgIGRldGFpbHMuYW1vdW50VmFsaWQgPSBmYWxzZTtcbiAgICByZXR1cm4ge1xuICAgICAgdmFsaWQ6IGZhbHNlLFxuICAgICAgZXJyb3I6IGBNaW5pbXVtIGJldCBpcyAke0JFVF9MSU1JVFMuTUlOX0JFVF9TT0x9IFNPTGAsXG4gICAgICB3YXJuaW5ncyxcbiAgICAgIGRldGFpbHMsXG4gICAgfTtcbiAgfVxuXG4gIGlmIChwYXJhbXMuYW1vdW50U29sID4gQkVUX0xJTUlUUy5NQVhfQkVUX1NPTCkge1xuICAgIGRldGFpbHMuYW1vdW50VmFsaWQgPSBmYWxzZTtcbiAgICByZXR1cm4ge1xuICAgICAgdmFsaWQ6IGZhbHNlLFxuICAgICAgZXJyb3I6IGBNYXhpbXVtIGJldCBpcyAke0JFVF9MSU1JVFMuTUFYX0JFVF9TT0x9IFNPTGAsXG4gICAgICB3YXJuaW5ncyxcbiAgICAgIGRldGFpbHMsXG4gICAgfTtcbiAgfVxuXG4gIC8vIEFtb3VudCB3YXJuaW5nc1xuICBpZiAocGFyYW1zLmFtb3VudFNvbCA+IDUwKSB7XG4gICAgd2FybmluZ3MucHVzaCgnTGFyZ2UgYmV0IGFtb3VudC4gRW5zdXJlIHlvdSB1bmRlcnN0YW5kIHRoZSBvZGRzIGJlZm9yZSBwbGFjaW5nLicpO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gTWFya2V0IFN0YXRlIFZhbGlkYXRpb25cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgaWYgKHBhcmFtcy5tYXJrZXRTdGF0dXMgIT09IE1BUktFVF9TVEFUVVMuQUNUSVZFKSB7XG4gICAgZGV0YWlscy5tYXJrZXRTdGF0ZVZhbGlkID0gZmFsc2U7XG4gICAgY29uc3Qgc3RhdHVzTmFtZSA9IGdldFN0YXR1c05hbWUocGFyYW1zLm1hcmtldFN0YXR1cyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHZhbGlkOiBmYWxzZSxcbiAgICAgIGVycm9yOiBgTWFya2V0IGlzICR7c3RhdHVzTmFtZX0sIG5vdCBhY2NlcHRpbmcgYmV0c2AsXG4gICAgICB3YXJuaW5ncyxcbiAgICAgIGRldGFpbHMsXG4gICAgfTtcbiAgfVxuXG4gIGlmIChwYXJhbXMuaXNQYXVzZWQpIHtcbiAgICBkZXRhaWxzLm1hcmtldFN0YXRlVmFsaWQgPSBmYWxzZTtcbiAgICByZXR1cm4ge1xuICAgICAgdmFsaWQ6IGZhbHNlLFxuICAgICAgZXJyb3I6ICdNYXJrZXQgaXMgcGF1c2VkJyxcbiAgICAgIHdhcm5pbmdzLFxuICAgICAgZGV0YWlscyxcbiAgICB9O1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gVGltaW5nIFZhbGlkYXRpb25cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgY29uc3QgZnJlZXplVGltZSA9IG5ldyBEYXRlKFxuICAgIHBhcmFtcy5jbG9zaW5nVGltZS5nZXRUaW1lKCkgLSBUSU1JTkcuQkVUVElOR19GUkVFWkVfU0VDT05EUyAqIDEwMDBcbiAgKTtcblxuICBpZiAobm93ID49IHBhcmFtcy5jbG9zaW5nVGltZSkge1xuICAgIGRldGFpbHMudGltaW5nVmFsaWQgPSBmYWxzZTtcbiAgICByZXR1cm4ge1xuICAgICAgdmFsaWQ6IGZhbHNlLFxuICAgICAgZXJyb3I6ICdCZXR0aW5nIGhhcyBjbG9zZWQnLFxuICAgICAgd2FybmluZ3MsXG4gICAgICBkZXRhaWxzLFxuICAgIH07XG4gIH1cblxuICBpZiAobm93ID49IGZyZWV6ZVRpbWUpIHtcbiAgICBkZXRhaWxzLnRpbWluZ1ZhbGlkID0gZmFsc2U7XG4gICAgY29uc3QgcmVtYWluaW5nTXMgPSBwYXJhbXMuY2xvc2luZ1RpbWUuZ2V0VGltZSgpIC0gbm93LmdldFRpbWUoKTtcbiAgICBjb25zdCByZW1haW5pbmdNaW4gPSBNYXRoLmNlaWwocmVtYWluaW5nTXMgLyA2MDAwMCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHZhbGlkOiBmYWxzZSxcbiAgICAgIGVycm9yOiBgQmV0dGluZyBpcyBmcm96ZW4gKCR7cmVtYWluaW5nTWlufSBtaW51dGVzIHVudGlsIGNsb3NlKWAsXG4gICAgICB3YXJuaW5ncyxcbiAgICAgIGRldGFpbHMsXG4gICAgfTtcbiAgfVxuXG4gIC8vIFRpbWluZyB3YXJuaW5nc1xuICBjb25zdCB0aW1lVG9GcmVlemVNcyA9IGZyZWV6ZVRpbWUuZ2V0VGltZSgpIC0gbm93LmdldFRpbWUoKTtcbiAgY29uc3QgdGltZVRvRnJlZXplTWluID0gTWF0aC5mbG9vcih0aW1lVG9GcmVlemVNcyAvIDYwMDAwKTtcbiAgaWYgKHRpbWVUb0ZyZWV6ZU1pbiA8IDMwKSB7XG4gICAgd2FybmluZ3MucHVzaChgQmV0dGluZyBmcmVlemVzIGluICR7dGltZVRvRnJlZXplTWlufSBtaW51dGVzYCk7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBBY2Nlc3MgVmFsaWRhdGlvbiAoV2hpdGVsaXN0KVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICBpZiAocGFyYW1zLmFjY2Vzc0dhdGUgPT09IEFDQ0VTU19HQVRFLldISVRFTElTVCkge1xuICAgIGlmIChwYXJhbXMudXNlcldoaXRlbGlzdGVkICE9PSB0cnVlKSB7XG4gICAgICBkZXRhaWxzLmFjY2Vzc1ZhbGlkID0gZmFsc2U7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2YWxpZDogZmFsc2UsXG4gICAgICAgIGVycm9yOiAnWW91IGFyZSBub3Qgd2hpdGVsaXN0ZWQgZm9yIHRoaXMgcHJpdmF0ZSBtYXJrZXQnLFxuICAgICAgICB3YXJuaW5ncyxcbiAgICAgICAgZGV0YWlscyxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgLy8gTGF5ZXItc3BlY2lmaWMgd2FybmluZ3NcbiAgaWYgKHBhcmFtcy5sYXllciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgbGF5ZXJOYW1lID0gTUFSS0VUX0xBWUVSX05BTUVTW3BhcmFtcy5sYXllcl0gfHwgJ1Vua25vd24nO1xuICAgIGlmIChwYXJhbXMubGF5ZXIgPT09IDEpIHsgLy8gTGFiXG4gICAgICB3YXJuaW5ncy5wdXNoKGBUaGlzIGlzIGEgJHtsYXllck5hbWV9IG1hcmtldCAoY29tbXVuaXR5LWNyZWF0ZWQpLiBEWU9SLmApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdmFsaWQ6IHRydWUsXG4gICAgd2FybmluZ3MsXG4gICAgZGV0YWlscyxcbiAgfTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIENMQUlNIFZBTElEQVRJT05cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogVmFsaWRhdGUgY2xhaW0gcGFyYW1ldGVycyBiZWZvcmUgYnVpbGRpbmcgY2xhaW0gdHJhbnNhY3Rpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlQ2xhaW0ocGFyYW1zOiBDbGFpbVZhbGlkYXRpb25QYXJhbXMpOiBDbGFpbVZhbGlkYXRpb24ge1xuICAvLyBBbHJlYWR5IGNsYWltZWRcbiAgaWYgKHBhcmFtcy5hbHJlYWR5Q2xhaW1lZCkge1xuICAgIHJldHVybiB7XG4gICAgICB2YWxpZDogZmFsc2UsXG4gICAgICBlcnJvcjogJ1Bvc2l0aW9uIGFscmVhZHkgY2xhaW1lZCcsXG4gICAgICBjYW5DbGFpbTogZmFsc2UsXG4gICAgICBpc1dpbm5lcjogZmFsc2UsXG4gICAgfTtcbiAgfVxuXG4gIC8vIE1hcmtldCBub3QgcmVzb2x2ZWRcbiAgaWYgKHBhcmFtcy5tYXJrZXRTdGF0dXMgIT09IE1BUktFVF9TVEFUVVMuUkVTT0xWRUQgJiZcbiAgICAgIHBhcmFtcy5tYXJrZXRTdGF0dXMgIT09IE1BUktFVF9TVEFUVVMuQ0FOQ0VMTEVEKSB7XG4gICAgY29uc3Qgc3RhdHVzTmFtZSA9IGdldFN0YXR1c05hbWUocGFyYW1zLm1hcmtldFN0YXR1cyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHZhbGlkOiBmYWxzZSxcbiAgICAgIGVycm9yOiBgTWFya2V0IGlzICR7c3RhdHVzTmFtZX0sIGNhbm5vdCBjbGFpbSB5ZXRgLFxuICAgICAgY2FuQ2xhaW06IGZhbHNlLFxuICAgICAgaXNXaW5uZXI6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyBDYW5jZWxsZWQgbWFya2V0IC0gZXZlcnlvbmUgY2FuIGNsYWltIHJlZnVuZFxuICBpZiAocGFyYW1zLm1hcmtldFN0YXR1cyA9PT0gTUFSS0VUX1NUQVRVUy5DQU5DRUxMRUQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdmFsaWQ6IHRydWUsXG4gICAgICBjYW5DbGFpbTogdHJ1ZSxcbiAgICAgIGlzV2lubmVyOiBmYWxzZSwgLy8gUmVmdW5kLCBub3Qgd2lubmluZ1xuICAgIH07XG4gIH1cblxuICAvLyBDaGVjayBpZiBwb3NpdGlvbiBpcyBvbiB3aW5uaW5nIHNpZGVcbiAgY29uc3QgaXNXaW5uZXIgPSAocGFyYW1zLnBvc2l0aW9uU2lkZSA9PT0gJ1llcycgJiYgcGFyYW1zLm1hcmtldE91dGNvbWUgPT09IDIpIHx8XG4gICAgICAgICAgICAgICAgICAgKHBhcmFtcy5wb3NpdGlvblNpZGUgPT09ICdObycgJiYgcGFyYW1zLm1hcmtldE91dGNvbWUgPT09IDMpO1xuXG4gIGlmICghaXNXaW5uZXIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdmFsaWQ6IGZhbHNlLFxuICAgICAgZXJyb3I6ICdQb3NpdGlvbiBpcyBvbiBsb3Npbmcgc2lkZSwgbm90aGluZyB0byBjbGFpbScsXG4gICAgICBjYW5DbGFpbTogZmFsc2UsXG4gICAgICBpc1dpbm5lcjogZmFsc2UsXG4gICAgfTtcbiAgfVxuXG4gIC8vIE5vdGhpbmcgdG8gY2xhaW0gaWYgYW1vdW50IGlzIDBcbiAgaWYgKHBhcmFtcy5wb3NpdGlvbkFtb3VudCA8PSAwKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHZhbGlkOiBmYWxzZSxcbiAgICAgIGVycm9yOiAnTm8gcG9zaXRpb24gYW1vdW50IHRvIGNsYWltJyxcbiAgICAgIGNhbkNsYWltOiBmYWxzZSxcbiAgICAgIGlzV2lubmVyOiB0cnVlLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHZhbGlkOiB0cnVlLFxuICAgIGNhbkNsYWltOiB0cnVlLFxuICAgIGlzV2lubmVyOiB0cnVlLFxuICB9O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gSEVMUEVSIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZnVuY3Rpb24gZ2V0U3RhdHVzTmFtZShzdGF0dXM6IG51bWJlcik6IHN0cmluZyB7XG4gIHN3aXRjaCAoc3RhdHVzKSB7XG4gICAgY2FzZSBNQVJLRVRfU1RBVFVTLkFDVElWRTogcmV0dXJuICdBY3RpdmUnO1xuICAgIGNhc2UgTUFSS0VUX1NUQVRVUy5DTE9TRUQ6IHJldHVybiAnQ2xvc2VkJztcbiAgICBjYXNlIE1BUktFVF9TVEFUVVMuUkVTT0xWRUQ6IHJldHVybiAnUmVzb2x2ZWQnO1xuICAgIGNhc2UgTUFSS0VUX1NUQVRVUy5DQU5DRUxMRUQ6IHJldHVybiAnQ2FuY2VsbGVkJztcbiAgICBjYXNlIE1BUktFVF9TVEFUVVMuUEFVU0VEOiByZXR1cm4gJ1BhdXNlZCc7XG4gICAgY2FzZSBNQVJLRVRfU1RBVFVTLlJFU09MVkVEX1BFTkRJTkc6IHJldHVybiAnUGVuZGluZyBSZXNvbHV0aW9uJztcbiAgICBjYXNlIE1BUktFVF9TVEFUVVMuRElTUFVURUQ6IHJldHVybiAnRGlzcHV0ZWQnO1xuICAgIGRlZmF1bHQ6IHJldHVybiAnVW5rbm93bic7XG4gIH1cbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgcXVvdGUgZm9yIGEgYmV0IChwYXJpLW11dHVlbClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUJldFF1b3RlKHBhcmFtczoge1xuICBiZXRBbW91bnRTb2w6IG51bWJlcjtcbiAgc2lkZTogJ1llcycgfCAnTm8nO1xuICBjdXJyZW50WWVzUG9vbDogbnVtYmVyO1xuICBjdXJyZW50Tm9Qb29sOiBudW1iZXI7XG4gIHBsYXRmb3JtRmVlQnBzOiBudW1iZXI7XG59KToge1xuICBleHBlY3RlZFBheW91dFNvbDogbnVtYmVyO1xuICBwb3RlbnRpYWxQcm9maXRTb2w6IG51bWJlcjtcbiAgZmVlU29sOiBudW1iZXI7XG4gIGltcGxpZWRPZGRzOiBudW1iZXI7XG4gIGRlY2ltYWxPZGRzOiBudW1iZXI7XG4gIG5ld1llc1Bvb2w6IG51bWJlcjtcbiAgbmV3Tm9Qb29sOiBudW1iZXI7XG59IHtcbiAgLy8gQ2FsY3VsYXRlIG5ldyBwb29scyBhZnRlciBiZXRcbiAgY29uc3QgbmV3WWVzUG9vbCA9IHBhcmFtcy5zaWRlID09PSAnWWVzJ1xuICAgID8gcGFyYW1zLmN1cnJlbnRZZXNQb29sICsgcGFyYW1zLmJldEFtb3VudFNvbFxuICAgIDogcGFyYW1zLmN1cnJlbnRZZXNQb29sO1xuICBjb25zdCBuZXdOb1Bvb2wgPSBwYXJhbXMuc2lkZSA9PT0gJ05vJ1xuICAgID8gcGFyYW1zLmN1cnJlbnROb1Bvb2wgKyBwYXJhbXMuYmV0QW1vdW50U29sXG4gICAgOiBwYXJhbXMuY3VycmVudE5vUG9vbDtcbiAgY29uc3QgbmV3VG90YWxQb29sID0gbmV3WWVzUG9vbCArIG5ld05vUG9vbDtcblxuICAvLyBDYWxjdWxhdGUgZXhwZWN0ZWQgcGF5b3V0IChwYXJpLW11dHVlbClcbiAgY29uc3Qgc2lkZVBvb2wgPSBwYXJhbXMuc2lkZSA9PT0gJ1llcycgPyBuZXdZZXNQb29sIDogbmV3Tm9Qb29sO1xuICBjb25zdCBleHBlY3RlZFBheW91dFNvbCA9IHNpZGVQb29sID4gMFxuICAgID8gKHBhcmFtcy5iZXRBbW91bnRTb2wgLyBzaWRlUG9vbCkgKiBuZXdUb3RhbFBvb2xcbiAgICA6IDA7XG5cbiAgLy8gQ2FsY3VsYXRlIHByb2ZpdCBhbmQgZmVlXG4gIGNvbnN0IGdyb3NzUHJvZml0ID0gZXhwZWN0ZWRQYXlvdXRTb2wgLSBwYXJhbXMuYmV0QW1vdW50U29sO1xuICBjb25zdCBmZWVTb2wgPSBncm9zc1Byb2ZpdCA+IDBcbiAgICA/IChncm9zc1Byb2ZpdCAqIHBhcmFtcy5wbGF0Zm9ybUZlZUJwcykgLyAxMDAwMFxuICAgIDogMDtcbiAgY29uc3QgcG90ZW50aWFsUHJvZml0U29sID0gZ3Jvc3NQcm9maXQgLSBmZWVTb2w7XG5cbiAgLy8gQ2FsY3VsYXRlIG9kZHNcbiAgY29uc3QgaW1wbGllZE9kZHMgPSBuZXdUb3RhbFBvb2wgPiAwXG4gICAgPyAoc2lkZVBvb2wgLyBuZXdUb3RhbFBvb2wpICogMTAwXG4gICAgOiA1MDtcbiAgY29uc3QgZGVjaW1hbE9kZHMgPSBzaWRlUG9vbCA+IDBcbiAgICA/IG5ld1RvdGFsUG9vbCAvIHNpZGVQb29sXG4gICAgOiAyO1xuXG4gIHJldHVybiB7XG4gICAgZXhwZWN0ZWRQYXlvdXRTb2w6IHJvdW5kNChleHBlY3RlZFBheW91dFNvbCksXG4gICAgcG90ZW50aWFsUHJvZml0U29sOiByb3VuZDQocG90ZW50aWFsUHJvZml0U29sKSxcbiAgICBmZWVTb2w6IHJvdW5kNChmZWVTb2wpLFxuICAgIGltcGxpZWRPZGRzOiByb3VuZDIoaW1wbGllZE9kZHMpLFxuICAgIGRlY2ltYWxPZGRzOiByb3VuZDIoZGVjaW1hbE9kZHMpLFxuICAgIG5ld1llc1Bvb2w6IHJvdW5kNChuZXdZZXNQb29sKSxcbiAgICBuZXdOb1Bvb2w6IHJvdW5kNChuZXdOb1Bvb2wpLFxuICB9O1xufVxuXG4vKipcbiAqIEVzdGltYXRlIGNsYWltIGFtb3VudCBmb3IgYSB3aW5uaW5nIHBvc2l0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlc3RpbWF0ZUNsYWltQW1vdW50KHBhcmFtczoge1xuICBwb3NpdGlvbkFtb3VudDogbnVtYmVyO1xuICBwb3NpdGlvblNpZGU6ICdZZXMnIHwgJ05vJztcbiAgdG90YWxZZXNQb29sOiBudW1iZXI7XG4gIHRvdGFsTm9Qb29sOiBudW1iZXI7XG4gIHBsYXRmb3JtRmVlQnBzOiBudW1iZXI7XG59KToge1xuICBncm9zc1BheW91dDogbnVtYmVyO1xuICBmZWU6IG51bWJlcjtcbiAgbmV0UGF5b3V0OiBudW1iZXI7XG59IHtcbiAgY29uc3QgdG90YWxQb29sID0gcGFyYW1zLnRvdGFsWWVzUG9vbCArIHBhcmFtcy50b3RhbE5vUG9vbDtcbiAgY29uc3Qgd2lubmluZ1Bvb2wgPSBwYXJhbXMucG9zaXRpb25TaWRlID09PSAnWWVzJ1xuICAgID8gcGFyYW1zLnRvdGFsWWVzUG9vbFxuICAgIDogcGFyYW1zLnRvdGFsTm9Qb29sO1xuXG4gIC8vIENhbGN1bGF0ZSBzaGFyZSBvZiB3aW5uaW5nIHBvb2xcbiAgY29uc3Qgc2hhcmVPZlBvb2wgPSB3aW5uaW5nUG9vbCA+IDBcbiAgICA/IHBhcmFtcy5wb3NpdGlvbkFtb3VudCAvIHdpbm5pbmdQb29sXG4gICAgOiAwO1xuXG4gIC8vIEdyb3NzIHBheW91dCBmcm9tIHRvdGFsIHBvb2xcbiAgY29uc3QgZ3Jvc3NQYXlvdXQgPSBzaGFyZU9mUG9vbCAqIHRvdGFsUG9vbDtcblxuICAvLyBDYWxjdWxhdGUgZmVlIG9uIHByb2ZpdCBvbmx5XG4gIGNvbnN0IHByb2ZpdCA9IGdyb3NzUGF5b3V0IC0gcGFyYW1zLnBvc2l0aW9uQW1vdW50O1xuICBjb25zdCBmZWUgPSBwcm9maXQgPiAwID8gKHByb2ZpdCAqIHBhcmFtcy5wbGF0Zm9ybUZlZUJwcykgLyAxMDAwMCA6IDA7XG5cbiAgcmV0dXJuIHtcbiAgICBncm9zc1BheW91dDogcm91bmQ0KGdyb3NzUGF5b3V0KSxcbiAgICBmZWU6IHJvdW5kNChmZWUpLFxuICAgIG5ldFBheW91dDogcm91bmQ0KGdyb3NzUGF5b3V0IC0gZmVlKSxcbiAgfTtcbn1cblxuLy8gUm91bmRpbmcgaGVscGVyc1xuZnVuY3Rpb24gcm91bmQyKG46IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBNYXRoLnJvdW5kKG4gKiAxMDApIC8gMTAwO1xufVxuXG5mdW5jdGlvbiByb3VuZDQobjogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobiAqIDEwMDAwKSAvIDEwMDAwO1xufVxuIl19
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Market Creation Validation Rules (v6.2 Compliant)
3
+ *
4
+ * Implements validation for:
5
+ * - Rule A: Event-based markets (12-24h buffer before event)
6
+ * - Rule B: Measurement-period markets (close before measurement starts)
7
+ * - Race market outcome validation
8
+ * - Question and timing constraints
9
+ */
10
+ export interface CreateMarketParams {
11
+ question: string;
12
+ closingTime: Date;
13
+ resolutionTime: Date;
14
+ layer: 'official' | 'lab' | 'private';
15
+ marketType?: 'event' | 'measurement';
16
+ eventTime?: Date;
17
+ measurementStart?: Date;
18
+ measurementEnd?: Date;
19
+ outcomes?: string[];
20
+ inviteHash?: string;
21
+ }
22
+ export interface CreationValidationResult {
23
+ valid: boolean;
24
+ errors: string[];
25
+ warnings: string[];
26
+ suggestions: string[];
27
+ computed: {
28
+ ruleType: 'A' | 'B' | 'unknown';
29
+ bufferHours?: number;
30
+ recommendedClosingTime?: string;
31
+ creationFeeSol: number;
32
+ platformFeeBps: number;
33
+ estimatedRentSol: number;
34
+ };
35
+ }
36
+ /**
37
+ * Validate market creation parameters
38
+ */
39
+ export declare function validateMarketCreation(params: CreateMarketParams): CreationValidationResult;
40
+ /**
41
+ * Calculate recommended resolution time from closing time
42
+ */
43
+ export declare function calculateResolutionTime(closingTime: Date, marketType: 'event' | 'measurement', eventTime?: Date): Date;
44
+ /**
45
+ * Calculate recommended closing time for event
46
+ */
47
+ export declare function calculateRecommendedClosingTime(eventTime: Date, bufferHours?: number): Date;
48
+ /**
49
+ * Get creation fee for layer
50
+ */
51
+ export declare function getCreationFee(layer: 'official' | 'lab' | 'private'): {
52
+ lamports: number;
53
+ sol: number;
54
+ };
55
+ /**
56
+ * Validate question format
57
+ */
58
+ export declare function validateQuestion(question: string): {
59
+ valid: boolean;
60
+ errors: string[];
61
+ suggestions: string[];
62
+ };
63
+ /**
64
+ * Validate race outcomes
65
+ */
66
+ export declare function validateRaceOutcomes(outcomes: string[]): {
67
+ valid: boolean;
68
+ errors: string[];
69
+ };