@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.
- package/README.md +294 -0
- package/dist/__tests__/full-test.d.ts +1 -0
- package/dist/__tests__/full-test.js +291 -0
- package/dist/builders/affiliate-transaction.d.ts +41 -0
- package/dist/builders/affiliate-transaction.js +123 -0
- package/dist/builders/bet-transaction.d.ts +70 -0
- package/dist/builders/bet-transaction.js +323 -0
- package/dist/builders/claim-transaction.d.ts +57 -0
- package/dist/builders/claim-transaction.js +196 -0
- package/dist/builders/creator-transaction.d.ts +49 -0
- package/dist/builders/creator-transaction.js +177 -0
- package/dist/builders/dispute-transaction.d.ts +81 -0
- package/dist/builders/dispute-transaction.js +215 -0
- package/dist/builders/index.d.ts +14 -0
- package/dist/builders/index.js +15 -0
- package/dist/builders/market-creation-tx.d.ts +65 -0
- package/dist/builders/market-creation-tx.js +362 -0
- package/dist/builders/market-management-transaction.d.ts +85 -0
- package/dist/builders/market-management-transaction.js +239 -0
- package/dist/builders/race-transaction.d.ts +67 -0
- package/dist/builders/race-transaction.js +242 -0
- package/dist/builders/resolution-transaction.d.ts +108 -0
- package/dist/builders/resolution-transaction.js +250 -0
- package/dist/builders/whitelist-transaction.d.ts +72 -0
- package/dist/builders/whitelist-transaction.js +179 -0
- package/dist/config.d.ts +138 -0
- package/dist/config.js +307 -0
- package/dist/handlers/agent-network.d.ts +81 -0
- package/dist/handlers/agent-network.js +332 -0
- package/dist/handlers/claims.d.ts +47 -0
- package/dist/handlers/claims.js +218 -0
- package/dist/handlers/market-creation.d.ts +154 -0
- package/dist/handlers/market-creation.js +290 -0
- package/dist/handlers/markets.d.ts +41 -0
- package/dist/handlers/markets.js +319 -0
- package/dist/handlers/positions.d.ts +40 -0
- package/dist/handlers/positions.js +244 -0
- package/dist/handlers/quote.d.ts +33 -0
- package/dist/handlers/quote.js +144 -0
- package/dist/handlers/race-markets.d.ts +54 -0
- package/dist/handlers/race-markets.js +308 -0
- package/dist/handlers/resolution.d.ts +43 -0
- package/dist/handlers/resolution.js +194 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +109 -0
- package/dist/resources.d.ts +13 -0
- package/dist/resources.js +336 -0
- package/dist/tools.d.ts +3109 -0
- package/dist/tools.js +1956 -0
- package/dist/validation/bet-rules.d.ts +82 -0
- package/dist/validation/bet-rules.js +276 -0
- package/dist/validation/creation-rules.d.ts +69 -0
- package/dist/validation/creation-rules.js +302 -0
- package/dist/validation/index.d.ts +6 -0
- package/dist/validation/index.js +7 -0
- package/dist/validation/market-rules.d.ts +60 -0
- package/dist/validation/market-rules.js +237 -0
- package/dist/validation/parimutuel-rules.d.ts +117 -0
- package/dist/validation/parimutuel-rules.js +270 -0
- package/package.json +52 -0
|
@@ -0,0 +1,302 @@
|
|
|
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
|
+
import { TIMING, FEES } from '../config.js';
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// CONSTANTS
|
|
13
|
+
// =============================================================================
|
|
14
|
+
const MAX_QUESTION_LENGTH = 200;
|
|
15
|
+
const MIN_OUTCOMES = 2;
|
|
16
|
+
const MAX_OUTCOMES = 10;
|
|
17
|
+
const MAX_OUTCOME_LABEL_LENGTH = 50;
|
|
18
|
+
const MIN_RESOLUTION_BUFFER_SECONDS = 600; // 10 minutes
|
|
19
|
+
const MAX_MARKET_DURATION_DAYS = 365;
|
|
20
|
+
// Rent estimates (lamports)
|
|
21
|
+
const MARKET_RENT = 5_000_000; // ~0.005 SOL
|
|
22
|
+
const RACE_MARKET_BASE_RENT = 8_000_000; // ~0.008 SOL
|
|
23
|
+
const RACE_OUTCOME_RENT = 500_000; // ~0.0005 SOL per outcome
|
|
24
|
+
// =============================================================================
|
|
25
|
+
// MAIN VALIDATION
|
|
26
|
+
// =============================================================================
|
|
27
|
+
/**
|
|
28
|
+
* Validate market creation parameters
|
|
29
|
+
*/
|
|
30
|
+
export function validateMarketCreation(params) {
|
|
31
|
+
const errors = [];
|
|
32
|
+
const warnings = [];
|
|
33
|
+
const suggestions = [];
|
|
34
|
+
// Determine rule type
|
|
35
|
+
let ruleType = 'unknown';
|
|
36
|
+
if (params.marketType === 'event' || params.eventTime) {
|
|
37
|
+
ruleType = 'A';
|
|
38
|
+
}
|
|
39
|
+
else if (params.marketType === 'measurement' || params.measurementStart) {
|
|
40
|
+
ruleType = 'B';
|
|
41
|
+
}
|
|
42
|
+
// =========================================================================
|
|
43
|
+
// Question Validation
|
|
44
|
+
// =========================================================================
|
|
45
|
+
if (!params.question || params.question.trim().length === 0) {
|
|
46
|
+
errors.push('Question is required');
|
|
47
|
+
}
|
|
48
|
+
else if (params.question.length > MAX_QUESTION_LENGTH) {
|
|
49
|
+
errors.push(`Question exceeds ${MAX_QUESTION_LENGTH} characters (got ${params.question.length})`);
|
|
50
|
+
}
|
|
51
|
+
if (!params.question.endsWith('?')) {
|
|
52
|
+
warnings.push('Question should end with a question mark for clarity');
|
|
53
|
+
}
|
|
54
|
+
// =========================================================================
|
|
55
|
+
// Timing Validation
|
|
56
|
+
// =========================================================================
|
|
57
|
+
const now = new Date();
|
|
58
|
+
// Closing time must be in future
|
|
59
|
+
if (params.closingTime <= now) {
|
|
60
|
+
errors.push('Closing time must be in the future');
|
|
61
|
+
}
|
|
62
|
+
// Maximum duration check
|
|
63
|
+
const durationDays = (params.closingTime.getTime() - now.getTime()) / (1000 * 60 * 60 * 24);
|
|
64
|
+
if (durationDays > MAX_MARKET_DURATION_DAYS) {
|
|
65
|
+
errors.push(`Market duration exceeds ${MAX_MARKET_DURATION_DAYS} days`);
|
|
66
|
+
}
|
|
67
|
+
// Resolution time must be after closing time
|
|
68
|
+
if (params.resolutionTime <= params.closingTime) {
|
|
69
|
+
errors.push('Resolution time must be after closing time');
|
|
70
|
+
}
|
|
71
|
+
// Minimum resolution buffer
|
|
72
|
+
const resolutionBufferSec = (params.resolutionTime.getTime() - params.closingTime.getTime()) / 1000;
|
|
73
|
+
if (resolutionBufferSec < MIN_RESOLUTION_BUFFER_SECONDS) {
|
|
74
|
+
errors.push(`Resolution buffer too short: ${resolutionBufferSec}s (min ${MIN_RESOLUTION_BUFFER_SECONDS}s)`);
|
|
75
|
+
}
|
|
76
|
+
// =========================================================================
|
|
77
|
+
// Rule A: Event-Based Validation
|
|
78
|
+
// =========================================================================
|
|
79
|
+
let bufferHours;
|
|
80
|
+
let recommendedClosingTime;
|
|
81
|
+
if (ruleType === 'A') {
|
|
82
|
+
if (!params.eventTime) {
|
|
83
|
+
errors.push('Event-based markets require event_time');
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// Event must be after closing
|
|
87
|
+
if (params.eventTime <= params.closingTime) {
|
|
88
|
+
errors.push('Event time must be after closing time');
|
|
89
|
+
}
|
|
90
|
+
// Calculate buffer
|
|
91
|
+
bufferHours = (params.eventTime.getTime() - params.closingTime.getTime()) / (1000 * 60 * 60);
|
|
92
|
+
if (bufferHours < TIMING.MIN_EVENT_BUFFER_HOURS) {
|
|
93
|
+
errors.push(`Event buffer too short: ${bufferHours.toFixed(1)}h. ` +
|
|
94
|
+
`Minimum ${TIMING.MIN_EVENT_BUFFER_HOURS}h required (v6.2 Rule A).`);
|
|
95
|
+
// Suggest corrected closing time
|
|
96
|
+
const suggestedClose = new Date(params.eventTime.getTime() - (TIMING.RECOMMENDED_EVENT_BUFFER_HOURS * 60 * 60 * 1000));
|
|
97
|
+
recommendedClosingTime = suggestedClose.toISOString();
|
|
98
|
+
suggestions.push(`Recommended closing time: ${recommendedClosingTime}`);
|
|
99
|
+
}
|
|
100
|
+
else if (bufferHours < 18) {
|
|
101
|
+
warnings.push(`Buffer is ${bufferHours.toFixed(1)}h. ` +
|
|
102
|
+
`Recommend 18-24h for safety margin (v6.2 Rule A).`);
|
|
103
|
+
}
|
|
104
|
+
// Event must be in future
|
|
105
|
+
if (params.eventTime <= now) {
|
|
106
|
+
errors.push('Event time must be in the future');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// =========================================================================
|
|
111
|
+
// Rule B: Measurement-Period Validation
|
|
112
|
+
// =========================================================================
|
|
113
|
+
if (ruleType === 'B') {
|
|
114
|
+
if (!params.measurementStart) {
|
|
115
|
+
errors.push('Measurement-period markets require measurement_start');
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// CRITICAL: Betting must close BEFORE measurement starts
|
|
119
|
+
if (params.closingTime >= params.measurementStart) {
|
|
120
|
+
const overlapHours = (params.closingTime.getTime() - params.measurementStart.getTime()) / (1000 * 60 * 60);
|
|
121
|
+
errors.push(`INVALID: Betting closes ${overlapHours.toFixed(1)}h AFTER measurement starts. ` +
|
|
122
|
+
`This allows information advantage! (v6.2 Rule B)`);
|
|
123
|
+
// Suggest corrected closing time
|
|
124
|
+
const suggestedClose = new Date(params.measurementStart.getTime() - (60 * 60 * 1000)); // 1h before
|
|
125
|
+
recommendedClosingTime = suggestedClose.toISOString();
|
|
126
|
+
suggestions.push(`Recommended closing time: ${recommendedClosingTime}`);
|
|
127
|
+
}
|
|
128
|
+
// Measurement end validation
|
|
129
|
+
if (params.measurementEnd) {
|
|
130
|
+
if (params.measurementEnd <= params.measurementStart) {
|
|
131
|
+
errors.push('Measurement end must be after measurement start');
|
|
132
|
+
}
|
|
133
|
+
const periodDays = (params.measurementEnd.getTime() - params.measurementStart.getTime()) / (1000 * 60 * 60 * 24);
|
|
134
|
+
if (periodDays > 7) {
|
|
135
|
+
warnings.push(`Long measurement period: ${periodDays.toFixed(0)} days. ` +
|
|
136
|
+
`Prefer 2-7 days for better UX (v6.2 guidance).`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// =========================================================================
|
|
142
|
+
// Race Market Validation
|
|
143
|
+
// =========================================================================
|
|
144
|
+
if (params.outcomes) {
|
|
145
|
+
if (params.outcomes.length < MIN_OUTCOMES) {
|
|
146
|
+
errors.push(`Race markets require at least ${MIN_OUTCOMES} outcomes`);
|
|
147
|
+
}
|
|
148
|
+
if (params.outcomes.length > MAX_OUTCOMES) {
|
|
149
|
+
errors.push(`Race markets limited to ${MAX_OUTCOMES} outcomes (got ${params.outcomes.length})`);
|
|
150
|
+
}
|
|
151
|
+
// Check outcome labels
|
|
152
|
+
for (let i = 0; i < params.outcomes.length; i++) {
|
|
153
|
+
const outcome = params.outcomes[i];
|
|
154
|
+
if (!outcome || outcome.trim().length === 0) {
|
|
155
|
+
errors.push(`Outcome ${i} is empty`);
|
|
156
|
+
}
|
|
157
|
+
else if (outcome.length > MAX_OUTCOME_LABEL_LENGTH) {
|
|
158
|
+
errors.push(`Outcome ${i} exceeds ${MAX_OUTCOME_LABEL_LENGTH} characters`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Check for duplicates
|
|
162
|
+
const uniqueOutcomes = new Set(params.outcomes.map(o => o.toLowerCase().trim()));
|
|
163
|
+
if (uniqueOutcomes.size !== params.outcomes.length) {
|
|
164
|
+
errors.push('Outcome labels must be unique');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// =========================================================================
|
|
168
|
+
// Layer-Specific Validation
|
|
169
|
+
// =========================================================================
|
|
170
|
+
let creationFeeSol;
|
|
171
|
+
let platformFeeBps;
|
|
172
|
+
switch (params.layer) {
|
|
173
|
+
case 'official':
|
|
174
|
+
creationFeeSol = FEES.OFFICIAL_CREATION_FEE / 1e9;
|
|
175
|
+
platformFeeBps = FEES.OFFICIAL_PLATFORM_FEE_BPS;
|
|
176
|
+
warnings.push('Official markets require admin approval');
|
|
177
|
+
break;
|
|
178
|
+
case 'private':
|
|
179
|
+
creationFeeSol = FEES.PRIVATE_CREATION_FEE / 1e9;
|
|
180
|
+
platformFeeBps = FEES.PRIVATE_PLATFORM_FEE_BPS;
|
|
181
|
+
if (!params.inviteHash) {
|
|
182
|
+
warnings.push('Private markets can use invite_hash for restricted access');
|
|
183
|
+
}
|
|
184
|
+
break;
|
|
185
|
+
case 'lab':
|
|
186
|
+
default:
|
|
187
|
+
creationFeeSol = FEES.LAB_CREATION_FEE / 1e9;
|
|
188
|
+
platformFeeBps = FEES.LAB_PLATFORM_FEE_BPS;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
// =========================================================================
|
|
192
|
+
// Rent Estimation
|
|
193
|
+
// =========================================================================
|
|
194
|
+
let estimatedRentSol;
|
|
195
|
+
if (params.outcomes) {
|
|
196
|
+
estimatedRentSol = (RACE_MARKET_BASE_RENT + (params.outcomes.length * RACE_OUTCOME_RENT)) / 1e9;
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
estimatedRentSol = MARKET_RENT / 1e9;
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
valid: errors.length === 0,
|
|
203
|
+
errors,
|
|
204
|
+
warnings,
|
|
205
|
+
suggestions,
|
|
206
|
+
computed: {
|
|
207
|
+
ruleType,
|
|
208
|
+
bufferHours,
|
|
209
|
+
recommendedClosingTime,
|
|
210
|
+
creationFeeSol,
|
|
211
|
+
platformFeeBps,
|
|
212
|
+
estimatedRentSol,
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
// =============================================================================
|
|
217
|
+
// HELPER FUNCTIONS
|
|
218
|
+
// =============================================================================
|
|
219
|
+
/**
|
|
220
|
+
* Calculate recommended resolution time from closing time
|
|
221
|
+
*/
|
|
222
|
+
export function calculateResolutionTime(closingTime, marketType, eventTime) {
|
|
223
|
+
if (marketType === 'event' && eventTime) {
|
|
224
|
+
// Resolution = event time + 1 hour buffer
|
|
225
|
+
return new Date(eventTime.getTime() + (60 * 60 * 1000));
|
|
226
|
+
}
|
|
227
|
+
// Default: closing time + 1 day
|
|
228
|
+
return new Date(closingTime.getTime() + (24 * 60 * 60 * 1000));
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Calculate recommended closing time for event
|
|
232
|
+
*/
|
|
233
|
+
export function calculateRecommendedClosingTime(eventTime, bufferHours = TIMING.RECOMMENDED_EVENT_BUFFER_HOURS) {
|
|
234
|
+
return new Date(eventTime.getTime() - (bufferHours * 60 * 60 * 1000));
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Get creation fee for layer
|
|
238
|
+
*/
|
|
239
|
+
export function getCreationFee(layer) {
|
|
240
|
+
let lamports;
|
|
241
|
+
switch (layer) {
|
|
242
|
+
case 'official':
|
|
243
|
+
lamports = FEES.OFFICIAL_CREATION_FEE;
|
|
244
|
+
break;
|
|
245
|
+
case 'private':
|
|
246
|
+
lamports = FEES.PRIVATE_CREATION_FEE;
|
|
247
|
+
break;
|
|
248
|
+
case 'lab':
|
|
249
|
+
default:
|
|
250
|
+
lamports = FEES.LAB_CREATION_FEE;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
return { lamports, sol: lamports / 1e9 };
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Validate question format
|
|
257
|
+
*/
|
|
258
|
+
export function validateQuestion(question) {
|
|
259
|
+
const errors = [];
|
|
260
|
+
const suggestions = [];
|
|
261
|
+
if (!question || question.trim().length === 0) {
|
|
262
|
+
errors.push('Question is required');
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
if (question.length > MAX_QUESTION_LENGTH) {
|
|
266
|
+
errors.push(`Question exceeds ${MAX_QUESTION_LENGTH} characters`);
|
|
267
|
+
}
|
|
268
|
+
if (!question.endsWith('?')) {
|
|
269
|
+
suggestions.push('Add a question mark at the end');
|
|
270
|
+
}
|
|
271
|
+
if (question.length < 10) {
|
|
272
|
+
suggestions.push('Consider a more descriptive question');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return { valid: errors.length === 0, errors, suggestions };
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Validate race outcomes
|
|
279
|
+
*/
|
|
280
|
+
export function validateRaceOutcomes(outcomes) {
|
|
281
|
+
const errors = [];
|
|
282
|
+
if (outcomes.length < MIN_OUTCOMES) {
|
|
283
|
+
errors.push(`Minimum ${MIN_OUTCOMES} outcomes required`);
|
|
284
|
+
}
|
|
285
|
+
if (outcomes.length > MAX_OUTCOMES) {
|
|
286
|
+
errors.push(`Maximum ${MAX_OUTCOMES} outcomes allowed`);
|
|
287
|
+
}
|
|
288
|
+
for (let i = 0; i < outcomes.length; i++) {
|
|
289
|
+
if (!outcomes[i] || outcomes[i].trim().length === 0) {
|
|
290
|
+
errors.push(`Outcome ${i + 1} is empty`);
|
|
291
|
+
}
|
|
292
|
+
else if (outcomes[i].length > MAX_OUTCOME_LABEL_LENGTH) {
|
|
293
|
+
errors.push(`Outcome ${i + 1} exceeds ${MAX_OUTCOME_LABEL_LENGTH} chars`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const unique = new Set(outcomes.map(o => o.toLowerCase().trim()));
|
|
297
|
+
if (unique.size !== outcomes.length) {
|
|
298
|
+
errors.push('Outcomes must be unique');
|
|
299
|
+
}
|
|
300
|
+
return { valid: errors.length === 0, errors };
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRpb24tcnVsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdmFsaWRhdGlvbi9jcmVhdGlvbi1ydWxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7R0FRRztBQUVILE9BQU8sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFnQixNQUFNLGNBQWMsQ0FBQztBQTRDMUQsZ0ZBQWdGO0FBQ2hGLFlBQVk7QUFDWixnRkFBZ0Y7QUFFaEYsTUFBTSxtQkFBbUIsR0FBRyxHQUFHLENBQUM7QUFDaEMsTUFBTSxZQUFZLEdBQUcsQ0FBQyxDQUFDO0FBQ3ZCLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztBQUN4QixNQUFNLHdCQUF3QixHQUFHLEVBQUUsQ0FBQztBQUNwQyxNQUFNLDZCQUE2QixHQUFHLEdBQUcsQ0FBQyxDQUFDLGFBQWE7QUFDeEQsTUFBTSx3QkFBd0IsR0FBRyxHQUFHLENBQUM7QUFFckMsNEJBQTRCO0FBQzVCLE1BQU0sV0FBVyxHQUFHLFNBQVMsQ0FBQyxDQUFDLGFBQWE7QUFDNUMsTUFBTSxxQkFBcUIsR0FBRyxTQUFTLENBQUMsQ0FBQyxhQUFhO0FBQ3RELE1BQU0saUJBQWlCLEdBQUcsT0FBTyxDQUFDLENBQUMsMEJBQTBCO0FBRTdELGdGQUFnRjtBQUNoRixrQkFBa0I7QUFDbEIsZ0ZBQWdGO0FBRWhGOztHQUVHO0FBQ0gsTUFBTSxVQUFVLHNCQUFzQixDQUFDLE1BQTBCO0lBQy9ELE1BQU0sTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUM1QixNQUFNLFFBQVEsR0FBYSxFQUFFLENBQUM7SUFDOUIsTUFBTSxXQUFXLEdBQWEsRUFBRSxDQUFDO0lBRWpDLHNCQUFzQjtJQUN0QixJQUFJLFFBQVEsR0FBMEIsU0FBUyxDQUFDO0lBQ2hELElBQUksTUFBTSxDQUFDLFVBQVUsS0FBSyxPQUFPLElBQUksTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ3RELFFBQVEsR0FBRyxHQUFHLENBQUM7SUFD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QUFXLENBQUMsQ0FBQztRQUMzQyxDQUFDO2FBQU0sSUFBSSxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLHdCQUF3QixFQUFFLENBQUM7WUFDekQsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLFlBQVksd0JBQXdCLFFBQVEsQ0FBQyxDQUFDO1FBQzVFLENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbEUsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNwQyxNQUFNLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUM7QUFDaEQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTWFya2V0IENyZWF0aW9uIFZhbGlkYXRpb24gUnVsZXMgKHY2LjIgQ29tcGxpYW50KVxuICpcbiAqIEltcGxlbWVudHMgdmFsaWRhdGlvbiBmb3I6XG4gKiAtIFJ1bGUgQTogRXZlbnQtYmFzZWQgbWFya2V0cyAoMTItMjRoIGJ1ZmZlciBiZWZvcmUgZXZlbnQpXG4gKiAtIFJ1bGUgQjogTWVhc3VyZW1lbnQtcGVyaW9kIG1hcmtldHMgKGNsb3NlIGJlZm9yZSBtZWFzdXJlbWVudCBzdGFydHMpXG4gKiAtIFJhY2UgbWFya2V0IG91dGNvbWUgdmFsaWRhdGlvblxuICogLSBRdWVzdGlvbiBhbmQgdGltaW5nIGNvbnN0cmFpbnRzXG4gKi9cblxuaW1wb3J0IHsgVElNSU5HLCBGRUVTLCBNQVJLRVRfTEFZRVIgfSBmcm9tICcuLi9jb25maWcuanMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVFlQRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3JlYXRlTWFya2V0UGFyYW1zIHtcbiAgcXVlc3Rpb246IHN0cmluZztcbiAgY2xvc2luZ1RpbWU6IERhdGU7XG4gIHJlc29sdXRpb25UaW1lOiBEYXRlO1xuICBsYXllcjogJ29mZmljaWFsJyB8ICdsYWInIHwgJ3ByaXZhdGUnO1xuXG4gIC8vIEV2ZW50LWJhc2VkIChSdWxlIEEpXG4gIG1hcmtldFR5cGU/OiAnZXZlbnQnIHwgJ21lYXN1cmVtZW50JztcbiAgZXZlbnRUaW1lPzogRGF0ZTtcblxuICAvLyBNZWFzdXJlbWVudC1wZXJpb2QgKFJ1bGUgQilcbiAgbWVhc3VyZW1lbnRTdGFydD86IERhdGU7XG4gIG1lYXN1cmVtZW50RW5kPzogRGF0ZTtcblxuICAvLyBSYWNlIG1hcmtldHNcbiAgb3V0Y29tZXM/OiBzdHJpbmdbXTtcblxuICAvLyBQcml2YXRlIG1hcmtldFxuICBpbnZpdGVIYXNoPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0aW9uVmFsaWRhdGlvblJlc3VsdCB7XG4gIHZhbGlkOiBib29sZWFuO1xuICBlcnJvcnM6IHN0cmluZ1tdO1xuICB3YXJuaW5nczogc3RyaW5nW107XG4gIHN1Z2dlc3Rpb25zOiBzdHJpbmdbXTtcblxuICAvLyBDb21wdXRlZCB2YWx1ZXNcbiAgY29tcHV0ZWQ6IHtcbiAgICBydWxlVHlwZTogJ0EnIHwgJ0InIHwgJ3Vua25vd24nO1xuICAgIGJ1ZmZlckhvdXJzPzogbnVtYmVyO1xuICAgIHJlY29tbWVuZGVkQ2xvc2luZ1RpbWU/OiBzdHJpbmc7XG4gICAgY3JlYXRpb25GZWVTb2w6IG51bWJlcjtcbiAgICBwbGF0Zm9ybUZlZUJwczogbnVtYmVyO1xuICAgIGVzdGltYXRlZFJlbnRTb2w6IG51bWJlcjtcbiAgfTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIENPTlNUQU5UU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuY29uc3QgTUFYX1FVRVNUSU9OX0xFTkdUSCA9IDIwMDtcbmNvbnN0IE1JTl9PVVRDT01FUyA9IDI7XG5jb25zdCBNQVhfT1VUQ09NRVMgPSAxMDtcbmNvbnN0IE1BWF9PVVRDT01FX0xBQkVMX0xFTkdUSCA9IDUwO1xuY29uc3QgTUlOX1JFU09MVVRJT05fQlVGRkVSX1NFQ09ORFMgPSA2MDA7IC8vIDEwIG1pbnV0ZXNcbmNvbnN0IE1BWF9NQVJLRVRfRFVSQVRJT05fREFZUyA9IDM2NTtcblxuLy8gUmVudCBlc3RpbWF0ZXMgKGxhbXBvcnRzKVxuY29uc3QgTUFSS0VUX1JFTlQgPSA1XzAwMF8wMDA7IC8vIH4wLjAwNSBTT0xcbmNvbnN0IFJBQ0VfTUFSS0VUX0JBU0VfUkVOVCA9IDhfMDAwXzAwMDsgLy8gfjAuMDA4IFNPTFxuY29uc3QgUkFDRV9PVVRDT01FX1JFTlQgPSA1MDBfMDAwOyAvLyB+MC4wMDA1IFNPTCBwZXIgb3V0Y29tZVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gTUFJTiBWQUxJREFUSU9OXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFZhbGlkYXRlIG1hcmtldCBjcmVhdGlvbiBwYXJhbWV0ZXJzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZU1hcmtldENyZWF0aW9uKHBhcmFtczogQ3JlYXRlTWFya2V0UGFyYW1zKTogQ3JlYXRpb25WYWxpZGF0aW9uUmVzdWx0IHtcbiAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xuICBjb25zdCB3YXJuaW5nczogc3RyaW5nW10gPSBbXTtcbiAgY29uc3Qgc3VnZ2VzdGlvbnM6IHN0cmluZ1tdID0gW107XG5cbiAgLy8gRGV0ZXJtaW5lIHJ1bGUgdHlwZVxuICBsZXQgcnVsZVR5cGU6ICdBJyB8ICdCJyB8ICd1bmtub3duJyA9ICd1bmtub3duJztcbiAgaWYgKHBhcmFtcy5tYXJrZXRUeXBlID09PSAnZXZlbnQnIHx8IHBhcmFtcy5ldmVudFRpbWUpIHtcbiAgICBydWxlVHlwZSA9ICdBJztcbiAgfSBlbHNlIGlmIChwYXJhbXMubWFya2V0VHlwZSA9PT0gJ21lYXN1cmVtZW50JyB8fCBwYXJhbXMubWVhc3VyZW1lbnRTdGFydCkge1xuICAgIHJ1bGVUeXBlID0gJ0InO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBRdWVzdGlvbiBWYWxpZGF0aW9uXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICBpZiAoIXBhcmFtcy5xdWVzdGlvbiB8fCBwYXJhbXMucXVlc3Rpb24udHJpbSgpLmxlbmd0aCA9PT0gMCkge1xuICAgIGVycm9ycy5wdXNoKCdRdWVzdGlvbiBpcyByZXF1aXJlZCcpO1xuICB9IGVsc2UgaWYgKHBhcmFtcy5xdWVzdGlvbi5sZW5ndGggPiBNQVhfUVVFU1RJT05fTEVOR1RIKSB7XG4gICAgZXJyb3JzLnB1c2goYFF1ZXN0aW9uIGV4Y2VlZHMgJHtNQVhfUVVFU1RJT05fTEVOR1RIfSBjaGFyYWN0ZXJzIChnb3QgJHtwYXJhbXMucXVlc3Rpb24ubGVuZ3RofSlgKTtcbiAgfVxuXG4gIGlmICghcGFyYW1zLnF1ZXN0aW9uLmVuZHNXaXRoKCc/JykpIHtcbiAgICB3YXJuaW5ncy5wdXNoKCdRdWVzdGlvbiBzaG91bGQgZW5kIHdpdGggYSBxdWVzdGlvbiBtYXJrIGZvciBjbGFyaXR5Jyk7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFRpbWluZyBWYWxpZGF0aW9uXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuXG4gIC8vIENsb3NpbmcgdGltZSBtdXN0IGJlIGluIGZ1dHVyZVxuICBpZiAocGFyYW1zLmNsb3NpbmdUaW1lIDw9IG5vdykge1xuICAgIGVycm9ycy5wdXNoKCdDbG9zaW5nIHRpbWUgbXVzdCBiZSBpbiB0aGUgZnV0dXJlJyk7XG4gIH1cblxuICAvLyBNYXhpbXVtIGR1cmF0aW9uIGNoZWNrXG4gIGNvbnN0IGR1cmF0aW9uRGF5cyA9IChwYXJhbXMuY2xvc2luZ1RpbWUuZ2V0VGltZSgpIC0gbm93LmdldFRpbWUoKSkgLyAoMTAwMCAqIDYwICogNjAgKiAyNCk7XG4gIGlmIChkdXJhdGlvbkRheXMgPiBNQVhfTUFSS0VUX0RVUkFUSU9OX0RBWVMpIHtcbiAgICBlcnJvcnMucHVzaChgTWFya2V0IGR1cmF0aW9uIGV4Y2VlZHMgJHtNQVhfTUFSS0VUX0RVUkFUSU9OX0RBWVN9IGRheXNgKTtcbiAgfVxuXG4gIC8vIFJlc29sdXRpb24gdGltZSBtdXN0IGJlIGFmdGVyIGNsb3NpbmcgdGltZVxuICBpZiAocGFyYW1zLnJlc29sdXRpb25UaW1lIDw9IHBhcmFtcy5jbG9zaW5nVGltZSkge1xuICAgIGVycm9ycy5wdXNoKCdSZXNvbHV0aW9uIHRpbWUgbXVzdCBiZSBhZnRlciBjbG9zaW5nIHRpbWUnKTtcbiAgfVxuXG4gIC8vIE1pbmltdW0gcmVzb2x1dGlvbiBidWZmZXJcbiAgY29uc3QgcmVzb2x1dGlvbkJ1ZmZlclNlYyA9IChwYXJhbXMucmVzb2x1dGlvblRpbWUuZ2V0VGltZSgpIC0gcGFyYW1zLmNsb3NpbmdUaW1lLmdldFRpbWUoKSkgLyAxMDAwO1xuICBpZiAocmVzb2x1dGlvbkJ1ZmZlclNlYyA8IE1JTl9SRVNPTFVUSU9OX0JVRkZFUl9TRUNPTkRTKSB7XG4gICAgZXJyb3JzLnB1c2goYFJlc29sdXRpb24gYnVmZmVyIHRvbyBzaG9ydDogJHtyZXNvbHV0aW9uQnVmZmVyU2VjfXMgKG1pbiAke01JTl9SRVNPTFVUSU9OX0JVRkZFUl9TRUNPTkRTfXMpYCk7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFJ1bGUgQTogRXZlbnQtQmFzZWQgVmFsaWRhdGlvblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgbGV0IGJ1ZmZlckhvdXJzOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGxldCByZWNvbW1lbmRlZENsb3NpbmdUaW1lOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgaWYgKHJ1bGVUeXBlID09PSAnQScpIHtcbiAgICBpZiAoIXBhcmFtcy5ldmVudFRpbWUpIHtcbiAgICAgIGVycm9ycy5wdXNoKCdFdmVudC1iYXNlZCBtYXJrZXRzIHJlcXVpcmUgZXZlbnRfdGltZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBFdmVudCBtdXN0IGJlIGFmdGVyIGNsb3NpbmdcbiAgICAgIGlmIChwYXJhbXMuZXZlbnRUaW1lIDw9IHBhcmFtcy5jbG9zaW5nVGltZSkge1xuICAgICAgICBlcnJvcnMucHVzaCgnRXZlbnQgdGltZSBtdXN0IGJlIGFmdGVyIGNsb3NpbmcgdGltZScpO1xuICAgICAgfVxuXG4gICAgICAvLyBDYWxjdWxhdGUgYnVmZmVyXG4gICAgICBidWZmZXJIb3VycyA9IChwYXJhbXMuZXZlbnRUaW1lLmdldFRpbWUoKSAtIHBhcmFtcy5jbG9zaW5nVGltZS5nZXRUaW1lKCkpIC8gKDEwMDAgKiA2MCAqIDYwKTtcblxuICAgICAgaWYgKGJ1ZmZlckhvdXJzIDwgVElNSU5HLk1JTl9FVkVOVF9CVUZGRVJfSE9VUlMpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goXG4gICAgICAgICAgYEV2ZW50IGJ1ZmZlciB0b28gc2hvcnQ6ICR7YnVmZmVySG91cnMudG9GaXhlZCgxKX1oLiBgICtcbiAgICAgICAgICBgTWluaW11bSAke1RJTUlORy5NSU5fRVZFTlRfQlVGRkVSX0hPVVJTfWggcmVxdWlyZWQgKHY2LjIgUnVsZSBBKS5gXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gU3VnZ2VzdCBjb3JyZWN0ZWQgY2xvc2luZyB0aW1lXG4gICAgICAgIGNvbnN0IHN1Z2dlc3RlZENsb3NlID0gbmV3IERhdGUoXG4gICAgICAgICAgcGFyYW1zLmV2ZW50VGltZS5nZXRUaW1lKCkgLSAoVElNSU5HLlJFQ09NTUVOREVEX0VWRU5UX0JVRkZFUl9IT1VSUyAqIDYwICogNjAgKiAxMDAwKVxuICAgICAgICApO1xuICAgICAgICByZWNvbW1lbmRlZENsb3NpbmdUaW1lID0gc3VnZ2VzdGVkQ2xvc2UudG9JU09TdHJpbmcoKTtcbiAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChgUmVjb21tZW5kZWQgY2xvc2luZyB0aW1lOiAke3JlY29tbWVuZGVkQ2xvc2luZ1RpbWV9YCk7XG4gICAgICB9IGVsc2UgaWYgKGJ1ZmZlckhvdXJzIDwgMTgpIHtcbiAgICAgICAgd2FybmluZ3MucHVzaChcbiAgICAgICAgICBgQnVmZmVyIGlzICR7YnVmZmVySG91cnMudG9GaXhlZCgxKX1oLiBgICtcbiAgICAgICAgICBgUmVjb21tZW5kIDE4LTI0aCBmb3Igc2FmZXR5IG1hcmdpbiAodjYuMiBSdWxlIEEpLmBcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gRXZlbnQgbXVzdCBiZSBpbiBmdXR1cmVcbiAgICAgIGlmIChwYXJhbXMuZXZlbnRUaW1lIDw9IG5vdykge1xuICAgICAgICBlcnJvcnMucHVzaCgnRXZlbnQgdGltZSBtdXN0IGJlIGluIHRoZSBmdXR1cmUnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFJ1bGUgQjogTWVhc3VyZW1lbnQtUGVyaW9kIFZhbGlkYXRpb25cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIGlmIChydWxlVHlwZSA9PT0gJ0InKSB7XG4gICAgaWYgKCFwYXJhbXMubWVhc3VyZW1lbnRTdGFydCkge1xuICAgICAgZXJyb3JzLnB1c2goJ01lYXN1cmVtZW50LXBlcmlvZCBtYXJrZXRzIHJlcXVpcmUgbWVhc3VyZW1lbnRfc3RhcnQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQ1JJVElDQUw6IEJldHRpbmcgbXVzdCBjbG9zZSBCRUZPUkUgbWVhc3VyZW1lbnQgc3RhcnRzXG4gICAgICBpZiAocGFyYW1zLmNsb3NpbmdUaW1lID49IHBhcmFtcy5tZWFzdXJlbWVudFN0YXJ0KSB7XG4gICAgICAgIGNvbnN0IG92ZXJsYXBIb3VycyA9IChwYXJhbXMuY2xvc2luZ1RpbWUuZ2V0VGltZSgpIC0gcGFyYW1zLm1lYXN1cmVtZW50U3RhcnQuZ2V0VGltZSgpKSAvICgxMDAwICogNjAgKiA2MCk7XG4gICAgICAgIGVycm9ycy5wdXNoKFxuICAgICAgICAgIGBJTlZBTElEOiBCZXR0aW5nIGNsb3NlcyAke292ZXJsYXBIb3Vycy50b0ZpeGVkKDEpfWggQUZURVIgbWVhc3VyZW1lbnQgc3RhcnRzLiBgICtcbiAgICAgICAgICBgVGhpcyBhbGxvd3MgaW5mb3JtYXRpb24gYWR2YW50YWdlISAodjYuMiBSdWxlIEIpYFxuICAgICAgICApO1xuXG4gICAgICAgIC8vIFN1Z2dlc3QgY29ycmVjdGVkIGNsb3NpbmcgdGltZVxuICAgICAgICBjb25zdCBzdWdnZXN0ZWRDbG9zZSA9IG5ldyBEYXRlKHBhcmFtcy5tZWFzdXJlbWVudFN0YXJ0LmdldFRpbWUoKSAtICg2MCAqIDYwICogMTAwMCkpOyAvLyAxaCBiZWZvcmVcbiAgICAgICAgcmVjb21tZW5kZWRDbG9zaW5nVGltZSA9IHN1Z2dlc3RlZENsb3NlLnRvSVNPU3RyaW5nKCk7XG4gICAgICAgIHN1Z2dlc3Rpb25zLnB1c2goYFJlY29tbWVuZGVkIGNsb3NpbmcgdGltZTogJHtyZWNvbW1lbmRlZENsb3NpbmdUaW1lfWApO1xuICAgICAgfVxuXG4gICAgICAvLyBNZWFzdXJlbWVudCBlbmQgdmFsaWRhdGlvblxuICAgICAgaWYgKHBhcmFtcy5tZWFzdXJlbWVudEVuZCkge1xuICAgICAgICBpZiAocGFyYW1zLm1lYXN1cmVtZW50RW5kIDw9IHBhcmFtcy5tZWFzdXJlbWVudFN0YXJ0KSB7XG4gICAgICAgICAgZXJyb3JzLnB1c2goJ01lYXN1cmVtZW50IGVuZCBtdXN0IGJlIGFmdGVyIG1lYXN1cmVtZW50IHN0YXJ0Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwZXJpb2REYXlzID0gKHBhcmFtcy5tZWFzdXJlbWVudEVuZC5nZXRUaW1lKCkgLSBwYXJhbXMubWVhc3VyZW1lbnRTdGFydC5nZXRUaW1lKCkpIC8gKDEwMDAgKiA2MCAqIDYwICogMjQpO1xuICAgICAgICBpZiAocGVyaW9kRGF5cyA+IDcpIHtcbiAgICAgICAgICB3YXJuaW5ncy5wdXNoKFxuICAgICAgICAgICAgYExvbmcgbWVhc3VyZW1lbnQgcGVyaW9kOiAke3BlcmlvZERheXMudG9GaXhlZCgwKX0gZGF5cy4gYCArXG4gICAgICAgICAgICBgUHJlZmVyIDItNyBkYXlzIGZvciBiZXR0ZXIgVVggKHY2LjIgZ3VpZGFuY2UpLmBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBSYWNlIE1hcmtldCBWYWxpZGF0aW9uXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICBpZiAocGFyYW1zLm91dGNvbWVzKSB7XG4gICAgaWYgKHBhcmFtcy5vdXRjb21lcy5sZW5ndGggPCBNSU5fT1VUQ09NRVMpIHtcbiAgICAgIGVycm9ycy5wdXNoKGBSYWNlIG1hcmtldHMgcmVxdWlyZSBhdCBsZWFzdCAke01JTl9PVVRDT01FU30gb3V0Y29tZXNgKTtcbiAgICB9XG4gICAgaWYgKHBhcmFtcy5vdXRjb21lcy5sZW5ndGggPiBNQVhfT1VUQ09NRVMpIHtcbiAgICAgIGVycm9ycy5wdXNoKGBSYWNlIG1hcmtldHMgbGltaXRlZCB0byAke01BWF9PVVRDT01FU30gb3V0Y29tZXMgKGdvdCAke3BhcmFtcy5vdXRjb21lcy5sZW5ndGh9KWApO1xuICAgIH1cblxuICAgIC8vIENoZWNrIG91dGNvbWUgbGFiZWxzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJhbXMub3V0Y29tZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG91dGNvbWUgPSBwYXJhbXMub3V0Y29tZXNbaV07XG4gICAgICBpZiAoIW91dGNvbWUgfHwgb3V0Y29tZS50cmltKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKGBPdXRjb21lICR7aX0gaXMgZW1wdHlgKTtcbiAgICAgIH0gZWxzZSBpZiAob3V0Y29tZS5sZW5ndGggPiBNQVhfT1VUQ09NRV9MQUJFTF9MRU5HVEgpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goYE91dGNvbWUgJHtpfSBleGNlZWRzICR7TUFYX09VVENPTUVfTEFCRUxfTEVOR1RIfSBjaGFyYWN0ZXJzYCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGR1cGxpY2F0ZXNcbiAgICBjb25zdCB1bmlxdWVPdXRjb21lcyA9IG5ldyBTZXQocGFyYW1zLm91dGNvbWVzLm1hcChvID0+IG8udG9Mb3dlckNhc2UoKS50cmltKCkpKTtcbiAgICBpZiAodW5pcXVlT3V0Y29tZXMuc2l6ZSAhPT0gcGFyYW1zLm91dGNvbWVzLmxlbmd0aCkge1xuICAgICAgZXJyb3JzLnB1c2goJ091dGNvbWUgbGFiZWxzIG11c3QgYmUgdW5pcXVlJyk7XG4gICAgfVxuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBMYXllci1TcGVjaWZpYyBWYWxpZGF0aW9uXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICBsZXQgY3JlYXRpb25GZWVTb2w6IG51bWJlcjtcbiAgbGV0IHBsYXRmb3JtRmVlQnBzOiBudW1iZXI7XG5cbiAgc3dpdGNoIChwYXJhbXMubGF5ZXIpIHtcbiAgICBjYXNlICdvZmZpY2lhbCc6XG4gICAgICBjcmVhdGlvbkZlZVNvbCA9IEZFRVMuT0ZGSUNJQUxfQ1JFQVRJT05fRkVFIC8gMWU5O1xuICAgICAgcGxhdGZvcm1GZWVCcHMgPSBGRUVTLk9GRklDSUFMX1BMQVRGT1JNX0ZFRV9CUFM7XG4gICAgICB3YXJuaW5ncy5wdXNoKCdPZmZpY2lhbCBtYXJrZXRzIHJlcXVpcmUgYWRtaW4gYXBwcm92YWwnKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3ByaXZhdGUnOlxuICAgICAgY3JlYXRpb25GZWVTb2wgPSBGRUVTLlBSSVZBVEVfQ1JFQVRJT05fRkVFIC8gMWU5O1xuICAgICAgcGxhdGZvcm1GZWVCcHMgPSBGRUVTLlBSSVZBVEVfUExBVEZPUk1fRkVFX0JQUztcbiAgICAgIGlmICghcGFyYW1zLmludml0ZUhhc2gpIHtcbiAgICAgICAgd2FybmluZ3MucHVzaCgnUHJpdmF0ZSBtYXJrZXRzIGNhbiB1c2UgaW52aXRlX2hhc2ggZm9yIHJlc3RyaWN0ZWQgYWNjZXNzJyk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdsYWInOlxuICAgIGRlZmF1bHQ6XG4gICAgICBjcmVhdGlvbkZlZVNvbCA9IEZFRVMuTEFCX0NSRUFUSU9OX0ZFRSAvIDFlOTtcbiAgICAgIHBsYXRmb3JtRmVlQnBzID0gRkVFUy5MQUJfUExBVEZPUk1fRkVFX0JQUztcbiAgICAgIGJyZWFrO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBSZW50IEVzdGltYXRpb25cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIGxldCBlc3RpbWF0ZWRSZW50U29sOiBudW1iZXI7XG4gIGlmIChwYXJhbXMub3V0Y29tZXMpIHtcbiAgICBlc3RpbWF0ZWRSZW50U29sID0gKFJBQ0VfTUFSS0VUX0JBU0VfUkVOVCArIChwYXJhbXMub3V0Y29tZXMubGVuZ3RoICogUkFDRV9PVVRDT01FX1JFTlQpKSAvIDFlOTtcbiAgfSBlbHNlIHtcbiAgICBlc3RpbWF0ZWRSZW50U29sID0gTUFSS0VUX1JFTlQgLyAxZTk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHZhbGlkOiBlcnJvcnMubGVuZ3RoID09PSAwLFxuICAgIGVycm9ycyxcbiAgICB3YXJuaW5ncyxcbiAgICBzdWdnZXN0aW9ucyxcbiAgICBjb21wdXRlZDoge1xuICAgICAgcnVsZVR5cGUsXG4gICAgICBidWZmZXJIb3VycyxcbiAgICAgIHJlY29tbWVuZGVkQ2xvc2luZ1RpbWUsXG4gICAgICBjcmVhdGlvbkZlZVNvbCxcbiAgICAgIHBsYXRmb3JtRmVlQnBzLFxuICAgICAgZXN0aW1hdGVkUmVudFNvbCxcbiAgICB9LFxuICB9O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gSEVMUEVSIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDYWxjdWxhdGUgcmVjb21tZW5kZWQgcmVzb2x1dGlvbiB0aW1lIGZyb20gY2xvc2luZyB0aW1lXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYWxjdWxhdGVSZXNvbHV0aW9uVGltZShcbiAgY2xvc2luZ1RpbWU6IERhdGUsXG4gIG1hcmtldFR5cGU6ICdldmVudCcgfCAnbWVhc3VyZW1lbnQnLFxuICBldmVudFRpbWU/OiBEYXRlXG4pOiBEYXRlIHtcbiAgaWYgKG1hcmtldFR5cGUgPT09ICdldmVudCcgJiYgZXZlbnRUaW1lKSB7XG4gICAgLy8gUmVzb2x1dGlvbiA9IGV2ZW50IHRpbWUgKyAxIGhvdXIgYnVmZmVyXG4gICAgcmV0dXJuIG5ldyBEYXRlKGV2ZW50VGltZS5nZXRUaW1lKCkgKyAoNjAgKiA2MCAqIDEwMDApKTtcbiAgfVxuICAvLyBEZWZhdWx0OiBjbG9zaW5nIHRpbWUgKyAxIGRheVxuICByZXR1cm4gbmV3IERhdGUoY2xvc2luZ1RpbWUuZ2V0VGltZSgpICsgKDI0ICogNjAgKiA2MCAqIDEwMDApKTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgcmVjb21tZW5kZWQgY2xvc2luZyB0aW1lIGZvciBldmVudFxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlUmVjb21tZW5kZWRDbG9zaW5nVGltZShcbiAgZXZlbnRUaW1lOiBEYXRlLFxuICBidWZmZXJIb3VyczogbnVtYmVyID0gVElNSU5HLlJFQ09NTUVOREVEX0VWRU5UX0JVRkZFUl9IT1VSU1xuKTogRGF0ZSB7XG4gIHJldHVybiBuZXcgRGF0ZShldmVudFRpbWUuZ2V0VGltZSgpIC0gKGJ1ZmZlckhvdXJzICogNjAgKiA2MCAqIDEwMDApKTtcbn1cblxuLyoqXG4gKiBHZXQgY3JlYXRpb24gZmVlIGZvciBsYXllclxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q3JlYXRpb25GZWUobGF5ZXI6ICdvZmZpY2lhbCcgfCAnbGFiJyB8ICdwcml2YXRlJyk6IHtcbiAgbGFtcG9ydHM6IG51bWJlcjtcbiAgc29sOiBudW1iZXI7XG59IHtcbiAgbGV0IGxhbXBvcnRzOiBudW1iZXI7XG4gIHN3aXRjaCAobGF5ZXIpIHtcbiAgICBjYXNlICdvZmZpY2lhbCc6XG4gICAgICBsYW1wb3J0cyA9IEZFRVMuT0ZGSUNJQUxfQ1JFQVRJT05fRkVFO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAncHJpdmF0ZSc6XG4gICAgICBsYW1wb3J0cyA9IEZFRVMuUFJJVkFURV9DUkVBVElPTl9GRUU7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdsYWInOlxuICAgIGRlZmF1bHQ6XG4gICAgICBsYW1wb3J0cyA9IEZFRVMuTEFCX0NSRUFUSU9OX0ZFRTtcbiAgICAgIGJyZWFrO1xuICB9XG4gIHJldHVybiB7IGxhbXBvcnRzLCBzb2w6IGxhbXBvcnRzIC8gMWU5IH07XG59XG5cbi8qKlxuICogVmFsaWRhdGUgcXVlc3Rpb24gZm9ybWF0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVF1ZXN0aW9uKHF1ZXN0aW9uOiBzdHJpbmcpOiB7XG4gIHZhbGlkOiBib29sZWFuO1xuICBlcnJvcnM6IHN0cmluZ1tdO1xuICBzdWdnZXN0aW9uczogc3RyaW5nW107XG59IHtcbiAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xuICBjb25zdCBzdWdnZXN0aW9uczogc3RyaW5nW10gPSBbXTtcblxuICBpZiAoIXF1ZXN0aW9uIHx8IHF1ZXN0aW9uLnRyaW0oKS5sZW5ndGggPT09IDApIHtcbiAgICBlcnJvcnMucHVzaCgnUXVlc3Rpb24gaXMgcmVxdWlyZWQnKTtcbiAgfSBlbHNlIHtcbiAgICBpZiAocXVlc3Rpb24ubGVuZ3RoID4gTUFYX1FVRVNUSU9OX0xFTkdUSCkge1xuICAgICAgZXJyb3JzLnB1c2goYFF1ZXN0aW9uIGV4Y2VlZHMgJHtNQVhfUVVFU1RJT05fTEVOR1RIfSBjaGFyYWN0ZXJzYCk7XG4gICAgfVxuICAgIGlmICghcXVlc3Rpb24uZW5kc1dpdGgoJz8nKSkge1xuICAgICAgc3VnZ2VzdGlvbnMucHVzaCgnQWRkIGEgcXVlc3Rpb24gbWFyayBhdCB0aGUgZW5kJyk7XG4gICAgfVxuICAgIGlmIChxdWVzdGlvbi5sZW5ndGggPCAxMCkge1xuICAgICAgc3VnZ2VzdGlvbnMucHVzaCgnQ29uc2lkZXIgYSBtb3JlIGRlc2NyaXB0aXZlIHF1ZXN0aW9uJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgdmFsaWQ6IGVycm9ycy5sZW5ndGggPT09IDAsIGVycm9ycywgc3VnZ2VzdGlvbnMgfTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSByYWNlIG91dGNvbWVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVJhY2VPdXRjb21lcyhvdXRjb21lczogc3RyaW5nW10pOiB7XG4gIHZhbGlkOiBib29sZWFuO1xuICBlcnJvcnM6IHN0cmluZ1tdO1xufSB7XG4gIGNvbnN0IGVycm9yczogc3RyaW5nW10gPSBbXTtcblxuICBpZiAob3V0Y29tZXMubGVuZ3RoIDwgTUlOX09VVENPTUVTKSB7XG4gICAgZXJyb3JzLnB1c2goYE1pbmltdW0gJHtNSU5fT1VUQ09NRVN9IG91dGNvbWVzIHJlcXVpcmVkYCk7XG4gIH1cbiAgaWYgKG91dGNvbWVzLmxlbmd0aCA+IE1BWF9PVVRDT01FUykge1xuICAgIGVycm9ycy5wdXNoKGBNYXhpbXVtICR7TUFYX09VVENPTUVTfSBvdXRjb21lcyBhbGxvd2VkYCk7XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IG91dGNvbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFvdXRjb21lc1tpXSB8fCBvdXRjb21lc1tpXS50cmltKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICBlcnJvcnMucHVzaChgT3V0Y29tZSAke2kgKyAxfSBpcyBlbXB0eWApO1xuICAgIH0gZWxzZSBpZiAob3V0Y29tZXNbaV0ubGVuZ3RoID4gTUFYX09VVENPTUVfTEFCRUxfTEVOR1RIKSB7XG4gICAgICBlcnJvcnMucHVzaChgT3V0Y29tZSAke2kgKyAxfSBleGNlZWRzICR7TUFYX09VVENPTUVfTEFCRUxfTEVOR1RIfSBjaGFyc2ApO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHVuaXF1ZSA9IG5ldyBTZXQob3V0Y29tZXMubWFwKG8gPT4gby50b0xvd2VyQ2FzZSgpLnRyaW0oKSkpO1xuICBpZiAodW5pcXVlLnNpemUgIT09IG91dGNvbWVzLmxlbmd0aCkge1xuICAgIGVycm9ycy5wdXNoKCdPdXRjb21lcyBtdXN0IGJlIHVuaXF1ZScpO1xuICB9XG5cbiAgcmV0dXJuIHsgdmFsaWQ6IGVycm9ycy5sZW5ndGggPT09IDAsIGVycm9ycyB9O1xufVxuIl19
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Engine Index
|
|
3
|
+
* Exports all validation functions and types
|
|
4
|
+
*/
|
|
5
|
+
export * from './market-rules.js';
|
|
6
|
+
export * from './bet-rules.js';
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdmFsaWRhdGlvbi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxjQUFjLG1CQUFtQixDQUFDO0FBQ2xDLGNBQWMsZ0JBQWdCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFZhbGlkYXRpb24gRW5naW5lIEluZGV4XG4gKiBFeHBvcnRzIGFsbCB2YWxpZGF0aW9uIGZ1bmN0aW9ucyBhbmQgdHlwZXNcbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL21hcmtldC1ydWxlcy5qcyc7XG5leHBvcnQgKiBmcm9tICcuL2JldC1ydWxlcy5qcyc7XG4iXX0=
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Market Validation Rules (v6.2)
|
|
3
|
+
*
|
|
4
|
+
* Implements timing validation for market creation based on:
|
|
5
|
+
* - Rule A: Event-Based Markets (single point in time)
|
|
6
|
+
* - Rule B: Measurement-Period Markets (outcome over time range)
|
|
7
|
+
*/
|
|
8
|
+
export interface MarketTimingParams {
|
|
9
|
+
question: string;
|
|
10
|
+
closingTime: Date;
|
|
11
|
+
marketType: 'event' | 'measurement';
|
|
12
|
+
eventTime?: Date;
|
|
13
|
+
measurementStart?: Date;
|
|
14
|
+
measurementEnd?: Date;
|
|
15
|
+
}
|
|
16
|
+
export interface MarketValidation {
|
|
17
|
+
valid: boolean;
|
|
18
|
+
ruleType: 'A' | 'B';
|
|
19
|
+
errors: string[];
|
|
20
|
+
warnings: string[];
|
|
21
|
+
suggestions: string[];
|
|
22
|
+
timing?: {
|
|
23
|
+
bufferHours?: number;
|
|
24
|
+
recommendedClose?: Date;
|
|
25
|
+
measurementDays?: number;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validate market timing parameters against v6.2 rules
|
|
30
|
+
*
|
|
31
|
+
* Rule A (Event-Based):
|
|
32
|
+
* - Betting closes BEFORE the event occurs
|
|
33
|
+
* - Minimum 12h buffer between close and event
|
|
34
|
+
* - Recommended 18-24h buffer for safety
|
|
35
|
+
*
|
|
36
|
+
* Rule B (Measurement-Period):
|
|
37
|
+
* - Betting must close BEFORE measurement starts
|
|
38
|
+
* - Measurement period should be well-defined
|
|
39
|
+
* - Prefer 2-7 day measurement periods for UX
|
|
40
|
+
*/
|
|
41
|
+
export declare function validateMarketTiming(params: MarketTimingParams): MarketValidation;
|
|
42
|
+
/**
|
|
43
|
+
* Generate timing suggestions based on market parameters
|
|
44
|
+
*/
|
|
45
|
+
export declare function generateTimingSuggestions(params: MarketTimingParams): string[];
|
|
46
|
+
/**
|
|
47
|
+
* Check if a market question follows best practices
|
|
48
|
+
*/
|
|
49
|
+
export declare function validateQuestionFormat(question: string): {
|
|
50
|
+
valid: boolean;
|
|
51
|
+
issues: string[];
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Calculate recommended times for a market
|
|
55
|
+
*/
|
|
56
|
+
export declare function calculateRecommendedTimes(eventOrMeasurementStart: Date, marketType: 'event' | 'measurement'): {
|
|
57
|
+
recommendedClose: Date;
|
|
58
|
+
latestClose: Date;
|
|
59
|
+
earliestClose: Date;
|
|
60
|
+
};
|