@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,237 @@
|
|
|
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
|
+
import { TIMING } from '../config.js';
|
|
9
|
+
// =============================================================================
|
|
10
|
+
// MAIN VALIDATION FUNCTION
|
|
11
|
+
// =============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Validate market timing parameters against v6.2 rules
|
|
14
|
+
*
|
|
15
|
+
* Rule A (Event-Based):
|
|
16
|
+
* - Betting closes BEFORE the event occurs
|
|
17
|
+
* - Minimum 12h buffer between close and event
|
|
18
|
+
* - Recommended 18-24h buffer for safety
|
|
19
|
+
*
|
|
20
|
+
* Rule B (Measurement-Period):
|
|
21
|
+
* - Betting must close BEFORE measurement starts
|
|
22
|
+
* - Measurement period should be well-defined
|
|
23
|
+
* - Prefer 2-7 day measurement periods for UX
|
|
24
|
+
*/
|
|
25
|
+
export function validateMarketTiming(params) {
|
|
26
|
+
const errors = [];
|
|
27
|
+
const warnings = [];
|
|
28
|
+
const suggestions = [];
|
|
29
|
+
const timing = {};
|
|
30
|
+
// Common validation: question length
|
|
31
|
+
if (params.question.length > 200) {
|
|
32
|
+
errors.push(`Question too long: ${params.question.length} chars (max 200)`);
|
|
33
|
+
}
|
|
34
|
+
if (params.question.length < 10) {
|
|
35
|
+
warnings.push(`Question may be too short: ${params.question.length} chars`);
|
|
36
|
+
}
|
|
37
|
+
// Common validation: closing time in future
|
|
38
|
+
const now = new Date();
|
|
39
|
+
if (params.closingTime <= now) {
|
|
40
|
+
errors.push('Closing time must be in the future');
|
|
41
|
+
}
|
|
42
|
+
// Common validation: closing time not too far
|
|
43
|
+
const maxClosingTime = new Date(now.getTime() + TIMING.MAX_MARKET_DURATION_DAYS * 24 * 60 * 60 * 1000);
|
|
44
|
+
if (params.closingTime > maxClosingTime) {
|
|
45
|
+
errors.push(`Closing time too far in future (max ${TIMING.MAX_MARKET_DURATION_DAYS} days)`);
|
|
46
|
+
}
|
|
47
|
+
// ==========================================================================
|
|
48
|
+
// Rule A: Event-Based Markets
|
|
49
|
+
// ==========================================================================
|
|
50
|
+
if (params.marketType === 'event') {
|
|
51
|
+
if (!params.eventTime) {
|
|
52
|
+
errors.push('Event-based markets require event_time');
|
|
53
|
+
return { valid: false, ruleType: 'A', errors, warnings, suggestions };
|
|
54
|
+
}
|
|
55
|
+
// Event time must be after closing time
|
|
56
|
+
if (params.eventTime <= params.closingTime) {
|
|
57
|
+
errors.push('Event time must be after closing time');
|
|
58
|
+
}
|
|
59
|
+
// Calculate buffer
|
|
60
|
+
const bufferMs = params.eventTime.getTime() - params.closingTime.getTime();
|
|
61
|
+
const bufferHours = bufferMs / (1000 * 60 * 60);
|
|
62
|
+
timing.bufferHours = Math.round(bufferHours * 10) / 10;
|
|
63
|
+
// Minimum buffer check (12 hours)
|
|
64
|
+
if (bufferHours < TIMING.MIN_EVENT_BUFFER_HOURS) {
|
|
65
|
+
errors.push(`Buffer too short: ${timing.bufferHours}h. ` +
|
|
66
|
+
`Minimum ${TIMING.MIN_EVENT_BUFFER_HOURS}h required between betting close and event.`);
|
|
67
|
+
}
|
|
68
|
+
else if (bufferHours < 18) {
|
|
69
|
+
warnings.push(`Buffer is ${timing.bufferHours}h. ` +
|
|
70
|
+
`Recommend ${TIMING.RECOMMENDED_EVENT_BUFFER_HOURS}h for safety margin.`);
|
|
71
|
+
}
|
|
72
|
+
// Suggest optimal closing time
|
|
73
|
+
const recommendedClose = new Date(params.eventTime.getTime() - TIMING.RECOMMENDED_EVENT_BUFFER_HOURS * 60 * 60 * 1000);
|
|
74
|
+
timing.recommendedClose = recommendedClose;
|
|
75
|
+
if (recommendedClose > now && params.closingTime > recommendedClose) {
|
|
76
|
+
suggestions.push(`Consider closing betting at ${recommendedClose.toISOString()} ` +
|
|
77
|
+
`(${TIMING.RECOMMENDED_EVENT_BUFFER_HOURS}h before event)`);
|
|
78
|
+
}
|
|
79
|
+
// Check for common mistakes
|
|
80
|
+
if (params.question.toLowerCase().includes('will') && !params.question.includes('?')) {
|
|
81
|
+
suggestions.push('Consider ending your question with a question mark for clarity');
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
valid: errors.length === 0,
|
|
85
|
+
ruleType: 'A',
|
|
86
|
+
errors,
|
|
87
|
+
warnings,
|
|
88
|
+
suggestions,
|
|
89
|
+
timing,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// ==========================================================================
|
|
93
|
+
// Rule B: Measurement-Period Markets
|
|
94
|
+
// ==========================================================================
|
|
95
|
+
if (params.marketType === 'measurement') {
|
|
96
|
+
if (!params.measurementStart) {
|
|
97
|
+
errors.push('Measurement-period markets require measurement_start');
|
|
98
|
+
return { valid: false, ruleType: 'B', errors, warnings, suggestions };
|
|
99
|
+
}
|
|
100
|
+
// CRITICAL: Betting must close BEFORE measurement starts
|
|
101
|
+
if (params.closingTime >= params.measurementStart) {
|
|
102
|
+
const overlapMs = params.closingTime.getTime() - params.measurementStart.getTime();
|
|
103
|
+
const overlapHours = overlapMs / (1000 * 60 * 60);
|
|
104
|
+
errors.push(`INVALID: Betting closes ${Math.round(overlapHours * 10) / 10}h AFTER measurement starts. ` +
|
|
105
|
+
`This allows information advantage! ` +
|
|
106
|
+
`Betting must close BEFORE measurement period begins.`);
|
|
107
|
+
}
|
|
108
|
+
// Calculate buffer before measurement
|
|
109
|
+
const bufferMs = params.measurementStart.getTime() - params.closingTime.getTime();
|
|
110
|
+
const bufferHours = bufferMs / (1000 * 60 * 60);
|
|
111
|
+
timing.bufferHours = Math.round(bufferHours * 10) / 10;
|
|
112
|
+
if (bufferHours < 1 && bufferHours > 0) {
|
|
113
|
+
warnings.push(`Very tight buffer (${timing.bufferHours}h) between betting close and measurement start. ` +
|
|
114
|
+
`Consider adding more time for late bettors.`);
|
|
115
|
+
}
|
|
116
|
+
// Measurement end validation
|
|
117
|
+
if (params.measurementEnd) {
|
|
118
|
+
if (params.measurementEnd <= params.measurementStart) {
|
|
119
|
+
errors.push('Measurement end must be after measurement start');
|
|
120
|
+
}
|
|
121
|
+
const periodMs = params.measurementEnd.getTime() - params.measurementStart.getTime();
|
|
122
|
+
const periodDays = periodMs / (1000 * 60 * 60 * 24);
|
|
123
|
+
timing.measurementDays = Math.round(periodDays * 10) / 10;
|
|
124
|
+
// UX guidance for measurement periods
|
|
125
|
+
if (periodDays > 30) {
|
|
126
|
+
warnings.push(`Very long measurement period: ${timing.measurementDays} days. ` +
|
|
127
|
+
`Consider shorter periods (2-7 days) for better user experience.`);
|
|
128
|
+
}
|
|
129
|
+
else if (periodDays > 7) {
|
|
130
|
+
warnings.push(`Long measurement period: ${timing.measurementDays} days. ` +
|
|
131
|
+
`Prefer 2-7 days for optimal engagement.`);
|
|
132
|
+
}
|
|
133
|
+
else if (periodDays < 1) {
|
|
134
|
+
suggestions.push(`Short measurement period (${Math.round(periodDays * 24)}h). ` +
|
|
135
|
+
`Ensure resolution can be determined within this timeframe.`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Suggest optimal closing time
|
|
139
|
+
const recommendedClose = new Date(params.measurementStart.getTime() - 2 * 60 * 60 * 1000 // 2 hours before measurement
|
|
140
|
+
);
|
|
141
|
+
timing.recommendedClose = recommendedClose;
|
|
142
|
+
if (recommendedClose > now && params.closingTime > recommendedClose) {
|
|
143
|
+
suggestions.push(`Consider closing betting at ${recommendedClose.toISOString()} ` +
|
|
144
|
+
`(2h before measurement period starts)`);
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
valid: errors.length === 0,
|
|
148
|
+
ruleType: 'B',
|
|
149
|
+
errors,
|
|
150
|
+
warnings,
|
|
151
|
+
suggestions,
|
|
152
|
+
timing,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// Unknown market type
|
|
156
|
+
errors.push(`Unknown market type: ${params.marketType}`);
|
|
157
|
+
return { valid: false, ruleType: 'A', errors, warnings, suggestions };
|
|
158
|
+
}
|
|
159
|
+
// =============================================================================
|
|
160
|
+
// HELPER FUNCTIONS
|
|
161
|
+
// =============================================================================
|
|
162
|
+
/**
|
|
163
|
+
* Generate timing suggestions based on market parameters
|
|
164
|
+
*/
|
|
165
|
+
export function generateTimingSuggestions(params) {
|
|
166
|
+
const suggestions = [];
|
|
167
|
+
const now = new Date();
|
|
168
|
+
if (params.marketType === 'event' && params.eventTime) {
|
|
169
|
+
// Suggest closing time for event-based markets
|
|
170
|
+
const optimalClose = new Date(params.eventTime.getTime() - TIMING.RECOMMENDED_EVENT_BUFFER_HOURS * 60 * 60 * 1000);
|
|
171
|
+
if (optimalClose > now) {
|
|
172
|
+
suggestions.push(`Optimal betting close: ${optimalClose.toISOString()}`);
|
|
173
|
+
}
|
|
174
|
+
// Suggest question format
|
|
175
|
+
if (!params.question.includes('?')) {
|
|
176
|
+
suggestions.push('End your question with "?" for clarity');
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (params.marketType === 'measurement' && params.measurementStart) {
|
|
180
|
+
// Suggest closing time for measurement markets
|
|
181
|
+
const optimalClose = new Date(params.measurementStart.getTime() - 2 * 60 * 60 * 1000);
|
|
182
|
+
if (optimalClose > now) {
|
|
183
|
+
suggestions.push(`Optimal betting close: ${optimalClose.toISOString()}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return suggestions;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Check if a market question follows best practices
|
|
190
|
+
*/
|
|
191
|
+
export function validateQuestionFormat(question) {
|
|
192
|
+
const issues = [];
|
|
193
|
+
// Length checks
|
|
194
|
+
if (question.length < 10) {
|
|
195
|
+
issues.push('Question too short (min 10 chars)');
|
|
196
|
+
}
|
|
197
|
+
if (question.length > 200) {
|
|
198
|
+
issues.push('Question too long (max 200 chars)');
|
|
199
|
+
}
|
|
200
|
+
// Format checks
|
|
201
|
+
if (!question.trim()) {
|
|
202
|
+
issues.push('Question cannot be empty');
|
|
203
|
+
}
|
|
204
|
+
// Best practice checks
|
|
205
|
+
if (!question.includes('?') && !question.toLowerCase().startsWith('will ')) {
|
|
206
|
+
issues.push('Consider phrasing as a yes/no question');
|
|
207
|
+
}
|
|
208
|
+
// Check for ambiguous language
|
|
209
|
+
const ambiguousTerms = ['maybe', 'probably', 'might', 'could possibly'];
|
|
210
|
+
for (const term of ambiguousTerms) {
|
|
211
|
+
if (question.toLowerCase().includes(term)) {
|
|
212
|
+
issues.push(`Avoid ambiguous term: "${term}"`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
valid: issues.length === 0,
|
|
217
|
+
issues,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Calculate recommended times for a market
|
|
222
|
+
*/
|
|
223
|
+
export function calculateRecommendedTimes(eventOrMeasurementStart, marketType) {
|
|
224
|
+
const buffer = marketType === 'event'
|
|
225
|
+
? TIMING.RECOMMENDED_EVENT_BUFFER_HOURS * 60 * 60 * 1000
|
|
226
|
+
: 2 * 60 * 60 * 1000; // 2 hours for measurement
|
|
227
|
+
const minBuffer = marketType === 'event'
|
|
228
|
+
? TIMING.MIN_EVENT_BUFFER_HOURS * 60 * 60 * 1000
|
|
229
|
+
: 1 * 60 * 60 * 1000; // 1 hour for measurement
|
|
230
|
+
const maxBuffer = 48 * 60 * 60 * 1000; // 48 hours max
|
|
231
|
+
return {
|
|
232
|
+
recommendedClose: new Date(eventOrMeasurementStart.getTime() - buffer),
|
|
233
|
+
latestClose: new Date(eventOrMeasurementStart.getTime() - minBuffer),
|
|
234
|
+
earliestClose: new Date(eventOrMeasurementStart.getTime() - maxBuffer),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFya2V0LXJ1bGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3ZhbGlkYXRpb24vbWFya2V0LXJ1bGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxjQUFjLENBQUM7QUE0QnRDLGdGQUFnRjtBQUNoRiwyQkFBMkI7QUFDM0IsZ0ZBQWdGO0FBRWhGOzs7Ozs7Ozs7Ozs7R0FZRztBQUNILE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxNQUEwQjtJQUM3RCxNQUFNLE1BQU0sR0FBYSxFQUFFLENBQUM7SUFDNUIsTUFBTSxRQUFRLEdBQWEsRUFBRSxDQUFDO0lBQzlCLE1BQU0sV0FBVyxHQUFhLEVBQUUsQ0FBQztJQUNqQyxNQUFNLE1BQU0sR0FBK0IsRUFBRSxDQUFDO0lBRTlDLHFDQUFxQztJQUNyQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sQ0FBQyxJQUFJLENBQUMsc0JBQXNCLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxrQkFBa0IsQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUFDRCxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLEVBQUUsRUFBRSxDQUFDO1FBQ2hDLFFBQVEsQ0FBQyxJQUFJLENBQUMsOEJBQThCLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxRQUFRLENBQUMsQ0FBQztJQUM5RSxDQUFDO0lBRUQsNENBQTRDO0lBQzVDLE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7SUFDdkIsSUFBSSxNQUFNLENBQUMsV0FBVyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQzlCLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0NBQW9DLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsOENBQThDO0lBQzlDLE1BQU0sY0FBYyxHQUFHLElBQUksSUFBSSxDQUFDLEdB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Q0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLHlCQUF5QixDQUN2Qyx1QkFBNkIsRUFDN0IsVUFBbUM7SUFNbkMsTUFBTSxNQUFNLEdBQUcsVUFBVSxLQUFLLE9BQU87UUFDbkMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyw4QkFBOEIsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUk7UUFDeEQsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLDBCQUEwQjtJQUVsRCxNQUFNLFNBQVMsR0FBRyxVQUFVLEtBQUssT0FBTztRQUN0QyxDQUFDLENBQUMsTUFBTSxDQUFDLHNCQUFzQixHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSTtRQUNoRCxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMseUJBQXlCO0lBRWpELE1BQU0sU0FBUyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLGVBQWU7SUFFdEQsT0FBTztRQUNMLGdCQUFnQixFQUFFLElBQUksSUFBSSxDQUFDLHVCQUF1QixDQUFDLE9BQU8sRUFBRSxHQUFHLE1BQU0sQ0FBQztRQUN0RSxXQUFXLEVBQUUsSUFBSSxJQUFJLENBQUMsdUJBQXVCLENBQUMsT0FBTyxFQUFFLEdBQUcsU0FBUyxDQUFDO1FBQ3BFLGFBQWEsRUFBRSxJQUFJLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxPQUFPLEVBQUUsR0FBRyxTQUFTLENBQUM7S0FDdkUsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE1hcmtldCBWYWxpZGF0aW9uIFJ1bGVzICh2Ni4yKVxuICpcbiAqIEltcGxlbWVudHMgdGltaW5nIHZhbGlkYXRpb24gZm9yIG1hcmtldCBjcmVhdGlvbiBiYXNlZCBvbjpcbiAqIC0gUnVsZSBBOiBFdmVudC1CYXNlZCBNYXJrZXRzIChzaW5nbGUgcG9pbnQgaW4gdGltZSlcbiAqIC0gUnVsZSBCOiBNZWFzdXJlbWVudC1QZXJpb2QgTWFya2V0cyAob3V0Y29tZSBvdmVyIHRpbWUgcmFuZ2UpXG4gKi9cblxuaW1wb3J0IHsgVElNSU5HIH0gZnJvbSAnLi4vY29uZmlnLmpzJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFRZUEVTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIE1hcmtldFRpbWluZ1BhcmFtcyB7XG4gIHF1ZXN0aW9uOiBzdHJpbmc7XG4gIGNsb3NpbmdUaW1lOiBEYXRlO1xuICBtYXJrZXRUeXBlOiAnZXZlbnQnIHwgJ21lYXN1cmVtZW50JztcbiAgZXZlbnRUaW1lPzogRGF0ZTtcbiAgbWVhc3VyZW1lbnRTdGFydD86IERhdGU7XG4gIG1lYXN1cmVtZW50RW5kPzogRGF0ZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNYXJrZXRWYWxpZGF0aW9uIHtcbiAgdmFsaWQ6IGJvb2xlYW47XG4gIHJ1bGVUeXBlOiAnQScgfCAnQic7XG4gIGVycm9yczogc3RyaW5nW107XG4gIHdhcm5pbmdzOiBzdHJpbmdbXTtcbiAgc3VnZ2VzdGlvbnM6IHN0cmluZ1tdO1xuICB0aW1pbmc/OiB7XG4gICAgYnVmZmVySG91cnM/OiBudW1iZXI7XG4gICAgcmVjb21tZW5kZWRDbG9zZT86IERhdGU7XG4gICAgbWVhc3VyZW1lbnREYXlzPzogbnVtYmVyO1xuICB9O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gTUFJTiBWQUxJREFUSU9OIEZVTkNUSU9OXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFZhbGlkYXRlIG1hcmtldCB0aW1pbmcgcGFyYW1ldGVycyBhZ2FpbnN0IHY2LjIgcnVsZXNcbiAqXG4gKiBSdWxlIEEgKEV2ZW50LUJhc2VkKTpcbiAqIC0gQmV0dGluZyBjbG9zZXMgQkVGT1JFIHRoZSBldmVudCBvY2N1cnNcbiAqIC0gTWluaW11bSAxMmggYnVmZmVyIGJldHdlZW4gY2xvc2UgYW5kIGV2ZW50XG4gKiAtIFJlY29tbWVuZGVkIDE4LTI0aCBidWZmZXIgZm9yIHNhZmV0eVxuICpcbiAqIFJ1bGUgQiAoTWVhc3VyZW1lbnQtUGVyaW9kKTpcbiAqIC0gQmV0dGluZyBtdXN0IGNsb3NlIEJFRk9SRSBtZWFzdXJlbWVudCBzdGFydHNcbiAqIC0gTWVhc3VyZW1lbnQgcGVyaW9kIHNob3VsZCBiZSB3ZWxsLWRlZmluZWRcbiAqIC0gUHJlZmVyIDItNyBkYXkgbWVhc3VyZW1lbnQgcGVyaW9kcyBmb3IgVVhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlTWFya2V0VGltaW5nKHBhcmFtczogTWFya2V0VGltaW5nUGFyYW1zKTogTWFya2V0VmFsaWRhdGlvbiB7XG4gIGNvbnN0IGVycm9yczogc3RyaW5nW10gPSBbXTtcbiAgY29uc3Qgd2FybmluZ3M6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IHN1Z2dlc3Rpb25zOiBzdHJpbmdbXSA9IFtdO1xuICBjb25zdCB0aW1pbmc6IE1hcmtldFZhbGlkYXRpb25bJ3RpbWluZyddID0ge307XG5cbiAgLy8gQ29tbW9uIHZhbGlkYXRpb246IHF1ZXN0aW9uIGxlbmd0aFxuICBpZiAocGFyYW1zLnF1ZXN0aW9uLmxlbmd0aCA+IDIwMCkge1xuICAgIGVycm9ycy5wdXNoKGBRdWVzdGlvbiB0b28gbG9uZzogJHtwYXJhbXMucXVlc3Rpb24ubGVuZ3RofSBjaGFycyAobWF4IDIwMClgKTtcbiAgfVxuICBpZiAocGFyYW1zLnF1ZXN0aW9uLmxlbmd0aCA8IDEwKSB7XG4gICAgd2FybmluZ3MucHVzaChgUXVlc3Rpb24gbWF5IGJlIHRvbyBzaG9ydDogJHtwYXJhbXMucXVlc3Rpb24ubGVuZ3RofSBjaGFyc2ApO1xuICB9XG5cbiAgLy8gQ29tbW9uIHZhbGlkYXRpb246IGNsb3NpbmcgdGltZSBpbiBmdXR1cmVcbiAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgaWYgKHBhcmFtcy5jbG9zaW5nVGltZSA8PSBub3cpIHtcbiAgICBlcnJvcnMucHVzaCgnQ2xvc2luZyB0aW1lIG11c3QgYmUgaW4gdGhlIGZ1dHVyZScpO1xuICB9XG5cbiAgLy8gQ29tbW9uIHZhbGlkYXRpb246IGNsb3NpbmcgdGltZSBub3QgdG9vIGZhclxuICBjb25zdCBtYXhDbG9zaW5nVGltZSA9IG5ldyBEYXRlKG5vdy5nZXRUaW1lKCkgKyBUSU1JTkcuTUFYX01BUktFVF9EVVJBVElPTl9EQVlTICogMjQgKiA2MCAqIDYwICogMTAwMCk7XG4gIGlmIChwYXJhbXMuY2xvc2luZ1RpbWUgPiBtYXhDbG9zaW5nVGltZSkge1xuICAgIGVycm9ycy5wdXNoKGBDbG9zaW5nIHRpbWUgdG9vIGZhciBpbiBmdXR1cmUgKG1heCAke1RJTUlORy5NQVhfTUFSS0VUX0RVUkFUSU9OX0RBWVN9IGRheXMpYCk7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBSdWxlIEE6IEV2ZW50LUJhc2VkIE1hcmtldHNcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgaWYgKHBhcmFtcy5tYXJrZXRUeXBlID09PSAnZXZlbnQnKSB7XG4gICAgaWYgKCFwYXJhbXMuZXZlbnRUaW1lKSB7XG4gICAgICBlcnJvcnMucHVzaCgnRXZlbnQtYmFzZWQgbWFya2V0cyByZXF1aXJlIGV2ZW50X3RpbWUnKTtcbiAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSwgcnVsZVR5cGU6ICdBJywgZXJyb3JzLCB3YXJuaW5ncywgc3VnZ2VzdGlvbnMgfTtcbiAgICB9XG5cbiAgICAvLyBFdmVudCB0aW1lIG11c3QgYmUgYWZ0ZXIgY2xvc2luZyB0aW1lXG4gICAgaWYgKHBhcmFtcy5ldmVudFRpbWUgPD0gcGFyYW1zLmNsb3NpbmdUaW1lKSB7XG4gICAgICBlcnJvcnMucHVzaCgnRXZlbnQgdGltZSBtdXN0IGJlIGFmdGVyIGNsb3NpbmcgdGltZScpO1xuICAgIH1cblxuICAgIC8vIENhbGN1bGF0ZSBidWZmZXJcbiAgICBjb25zdCBidWZmZXJNcyA9IHBhcmFtcy5ldmVudFRpbWUuZ2V0VGltZSgpIC0gcGFyYW1zLmNsb3NpbmdUaW1lLmdldFRpbWUoKTtcbiAgICBjb25zdCBidWZmZXJIb3VycyA9IGJ1ZmZlck1zIC8gKDEwMDAgKiA2MCAqIDYwKTtcbiAgICB0aW1pbmcuYnVmZmVySG91cnMgPSBNYXRoLnJvdW5kKGJ1ZmZlckhvdXJzICogMTApIC8gMTA7XG5cbiAgICAvLyBNaW5pbXVtIGJ1ZmZlciBjaGVjayAoMTIgaG91cnMpXG4gICAgaWYgKGJ1ZmZlckhvdXJzIDwgVElNSU5HLk1JTl9FVkVOVF9CVUZGRVJfSE9VUlMpIHtcbiAgICAgIGVycm9ycy5wdXNoKFxuICAgICAgICBgQnVmZmVyIHRvbyBzaG9ydDogJHt0aW1pbmcuYnVmZmVySG91cnN9aC4gYCArXG4gICAgICAgIGBNaW5pbXVtICR7VElNSU5HLk1JTl9FVkVOVF9CVUZGRVJfSE9VUlN9aCByZXF1aXJlZCBiZXR3ZWVuIGJldHRpbmcgY2xvc2UgYW5kIGV2ZW50LmBcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmIChidWZmZXJIb3VycyA8IDE4KSB7XG4gICAgICB3YXJuaW5ncy5wdXNoKFxuICAgICAgICBgQnVmZmVyIGlzICR7dGltaW5nLmJ1ZmZlckhvdXJzfWguIGAgK1xuICAgICAgICBgUmVjb21tZW5kICR7VElNSU5HLlJFQ09NTUVOREVEX0VWRU5UX0JVRkZFUl9IT1VSU31oIGZvciBzYWZldHkgbWFyZ2luLmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gU3VnZ2VzdCBvcHRpbWFsIGNsb3NpbmcgdGltZVxuICAgIGNvbnN0IHJlY29tbWVuZGVkQ2xvc2UgPSBuZXcgRGF0ZShcbiAgICAgIHBhcmFtcy5ldmVudFRpbWUuZ2V0VGltZSgpIC0gVElNSU5HLlJFQ09NTUVOREVEX0VWRU5UX0JVRkZFUl9IT1VSUyAqIDYwICogNjAgKiAxMDAwXG4gICAgKTtcbiAgICB0aW1pbmcucmVjb21tZW5kZWRDbG9zZSA9IHJlY29tbWVuZGVkQ2xvc2U7XG5cbiAgICBpZiAocmVjb21tZW5kZWRDbG9zZSA+IG5vdyAmJiBwYXJhbXMuY2xvc2luZ1RpbWUgPiByZWNvbW1lbmRlZENsb3NlKSB7XG4gICAgICBzdWdnZXN0aW9ucy5wdXNoKFxuICAgICAgICBgQ29uc2lkZXIgY2xvc2luZyBiZXR0aW5nIGF0ICR7cmVjb21tZW5kZWRDbG9zZS50b0lTT1N0cmluZygpfSBgICtcbiAgICAgICAgYCgke1RJTUlORy5SRUNPTU1FTkRFRF9FVkVOVF9CVUZGRVJfSE9VUlN9aCBiZWZvcmUgZXZlbnQpYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBmb3IgY29tbW9uIG1pc3Rha2VzXG4gICAgaWYgKHBhcmFtcy5xdWVzdGlvbi50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCd3aWxsJykgJiYgIXBhcmFtcy5xdWVzdGlvbi5pbmNsdWRlcygnPycpKSB7XG4gICAgICBzdWdnZXN0aW9ucy5wdXNoKCdDb25zaWRlciBlbmRpbmcgeW91ciBxdWVzdGlvbiB3aXRoIGEgcXVlc3Rpb24gbWFyayBmb3IgY2xhcml0eScpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB2YWxpZDogZXJyb3JzLmxlbmd0aCA9PT0gMCxcbiAgICAgIHJ1bGVUeXBlOiAnQScsXG4gICAgICBlcnJvcnMsXG4gICAgICB3YXJuaW5ncyxcbiAgICAgIHN1Z2dlc3Rpb25zLFxuICAgICAgdGltaW5nLFxuICAgIH07XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBSdWxlIEI6IE1lYXN1cmVtZW50LVBlcmlvZCBNYXJrZXRzXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIGlmIChwYXJhbXMubWFya2V0VHlwZSA9PT0gJ21lYXN1cmVtZW50Jykge1xuICAgIGlmICghcGFyYW1zLm1lYXN1cmVtZW50U3RhcnQpIHtcbiAgICAgIGVycm9ycy5wdXNoKCdNZWFzdXJlbWVudC1wZXJpb2QgbWFya2V0cyByZXF1aXJlIG1lYXN1cmVtZW50X3N0YXJ0Jyk7XG4gICAgICByZXR1cm4geyB2YWxpZDogZmFsc2UsIHJ1bGVUeXBlOiAnQicsIGVycm9ycywgd2FybmluZ3MsIHN1Z2dlc3Rpb25zIH07XG4gICAgfVxuXG4gICAgLy8gQ1JJVElDQUw6IEJldHRpbmcgbXVzdCBjbG9zZSBCRUZPUkUgbWVhc3VyZW1lbnQgc3RhcnRzXG4gICAgaWYgKHBhcmFtcy5jbG9zaW5nVGltZSA+PSBwYXJhbXMubWVhc3VyZW1lbnRTdGFydCkge1xuICAgICAgY29uc3Qgb3ZlcmxhcE1zID0gcGFyYW1zLmNsb3NpbmdUaW1lLmdldFRpbWUoKSAtIHBhcmFtcy5tZWFzdXJlbWVudFN0YXJ0LmdldFRpbWUoKTtcbiAgICAgIGNvbnN0IG92ZXJsYXBIb3VycyA9IG92ZXJsYXBNcyAvICgxMDAwICogNjAgKiA2MCk7XG4gICAgICBlcnJvcnMucHVzaChcbiAgICAgICAgYElOVkFMSUQ6IEJldHRpbmcgY2xvc2VzICR7TWF0aC5yb3VuZChvdmVybGFwSG91cnMgKiAxMCkgLyAxMH1oIEFGVEVSIG1lYXN1cmVtZW50IHN0YXJ0cy4gYCArXG4gICAgICAgIGBUaGlzIGFsbG93cyBpbmZvcm1hdGlvbiBhZHZhbnRhZ2UhIGAgK1xuICAgICAgICBgQmV0dGluZyBtdXN0IGNsb3NlIEJFRk9SRSBtZWFzdXJlbWVudCBwZXJpb2QgYmVnaW5zLmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gQ2FsY3VsYXRlIGJ1ZmZlciBiZWZvcmUgbWVhc3VyZW1lbnRcbiAgICBjb25zdCBidWZmZXJNcyA9IHBhcmFtcy5tZWFzdXJlbWVudFN0YXJ0LmdldFRpbWUoKSAtIHBhcmFtcy5jbG9zaW5nVGltZS5nZXRUaW1lKCk7XG4gICAgY29uc3QgYnVmZmVySG91cnMgPSBidWZmZXJNcyAvICgxMDAwICogNjAgKiA2MCk7XG4gICAgdGltaW5nLmJ1ZmZlckhvdXJzID0gTWF0aC5yb3VuZChidWZmZXJIb3VycyAqIDEwKSAvIDEwO1xuXG4gICAgaWYgKGJ1ZmZlckhvdXJzIDwgMSAmJiBidWZmZXJIb3VycyA+IDApIHtcbiAgICAgIHdhcm5pbmdzLnB1c2goXG4gICAgICAgIGBWZXJ5IHRpZ2h0IGJ1ZmZlciAoJHt0aW1pbmcuYnVmZmVySG91cnN9aCkgYmV0d2VlbiBiZXR0aW5nIGNsb3NlIGFuZCBtZWFzdXJlbWVudCBzdGFydC4gYCArXG4gICAgICAgIGBDb25zaWRlciBhZGRpbmcgbW9yZSB0aW1lIGZvciBsYXRlIGJldHRvcnMuYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBNZWFzdXJlbWVudCBlbmQgdmFsaWRhdGlvblxuICAgIGlmIChwYXJhbXMubWVhc3VyZW1lbnRFbmQpIHtcbiAgICAgIGlmIChwYXJhbXMubWVhc3VyZW1lbnRFbmQgPD0gcGFyYW1zLm1lYXN1cmVtZW50U3RhcnQpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goJ01lYXN1cmVtZW50IGVuZCBtdXN0IGJlIGFmdGVyIG1lYXN1cmVtZW50IHN0YXJ0Jyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBlcmlvZE1zID0gcGFyYW1zLm1lYXN1cmVtZW50RW5kLmdldFRpbWUoKSAtIHBhcmFtcy5tZWFzdXJlbWVudFN0YXJ0LmdldFRpbWUoKTtcbiAgICAgIGNvbnN0IHBlcmlvZERheXMgPSBwZXJpb2RNcyAvICgxMDAwICogNjAgKiA2MCAqIDI0KTtcbiAgICAgIHRpbWluZy5tZWFzdXJlbWVudERheXMgPSBNYXRoLnJvdW5kKHBlcmlvZERheXMgKiAxMCkgLyAxMDtcblxuICAgICAgLy8gVVggZ3VpZGFuY2UgZm9yIG1lYXN1cmVtZW50IHBlcmlvZHNcbiAgICAgIGlmIChwZXJpb2REYXlzID4gMzApIHtcbiAgICAgICAgd2FybmluZ3MucHVzaChcbiAgICAgICAgICBgVmVyeSBsb25nIG1lYXN1cmVtZW50IHBlcmlvZDogJHt0aW1pbmcubWVhc3VyZW1lbnREYXlzfSBkYXlzLiBgICtcbiAgICAgICAgICBgQ29uc2lkZXIgc2hvcnRlciBwZXJpb2RzICgyLTcgZGF5cykgZm9yIGJldHRlciB1c2VyIGV4cGVyaWVuY2UuYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChwZXJpb2REYXlzID4gNykge1xuICAgICAgICB3YXJuaW5ncy5wdXNoKFxuICAgICAgICAgIGBMb25nIG1lYXN1cmVtZW50IHBlcmlvZDogJHt0aW1pbmcubWVhc3VyZW1lbnREYXlzfSBkYXlzLiBgICtcbiAgICAgICAgICBgUHJlZmVyIDItNyBkYXlzIGZvciBvcHRpbWFsIGVuZ2FnZW1lbnQuYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChwZXJpb2REYXlzIDwgMSkge1xuICAgICAgICBzdWdnZXN0aW9ucy5wdXNoKFxuICAgICAgICAgIGBTaG9ydCBtZWFzdXJlbWVudCBwZXJpb2QgKCR7TWF0aC5yb3VuZChwZXJpb2REYXlzICogMjQpfWgpLiBgICtcbiAgICAgICAgICBgRW5zdXJlIHJlc29sdXRpb24gY2FuIGJlIGRldGVybWluZWQgd2l0aGluIHRoaXMgdGltZWZyYW1lLmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTdWdnZXN0IG9wdGltYWwgY2xvc2luZyB0aW1lXG4gICAgY29uc3QgcmVjb21tZW5kZWRDbG9zZSA9IG5ldyBEYXRlKFxuICAgICAgcGFyYW1zLm1lYXN1cmVtZW50U3RhcnQuZ2V0VGltZSgpIC0gMiAqIDYwICogNjAgKiAxMDAwIC8vIDIgaG91cnMgYmVmb3JlIG1lYXN1cmVtZW50XG4gICAgKTtcbiAgICB0aW1pbmcucmVjb21tZW5kZWRDbG9zZSA9IHJlY29tbWVuZGVkQ2xvc2U7XG5cbiAgICBpZiAocmVjb21tZW5kZWRDbG9zZSA+IG5vdyAmJiBwYXJhbXMuY2xvc2luZ1RpbWUgPiByZWNvbW1lbmRlZENsb3NlKSB7XG4gICAgICBzdWdnZXN0aW9ucy5wdXNoKFxuICAgICAgICBgQ29uc2lkZXIgY2xvc2luZyBiZXR0aW5nIGF0ICR7cmVjb21tZW5kZWRDbG9zZS50b0lTT1N0cmluZygpfSBgICtcbiAgICAgICAgYCgyaCBiZWZvcmUgbWVhc3VyZW1lbnQgcGVyaW9kIHN0YXJ0cylgXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB2YWxpZDogZXJyb3JzLmxlbmd0aCA9PT0gMCxcbiAgICAgIHJ1bGVUeXBlOiAnQicsXG4gICAgICBlcnJvcnMsXG4gICAgICB3YXJuaW5ncyxcbiAgICAgIHN1Z2dlc3Rpb25zLFxuICAgICAgdGltaW5nLFxuICAgIH07XG4gIH1cblxuICAvLyBVbmtub3duIG1hcmtldCB0eXBlXG4gIGVycm9ycy5wdXNoKGBVbmtub3duIG1hcmtldCB0eXBlOiAke3BhcmFtcy5tYXJrZXRUeXBlfWApO1xuICByZXR1cm4geyB2YWxpZDogZmFsc2UsIHJ1bGVUeXBlOiAnQScsIGVycm9ycywgd2FybmluZ3MsIHN1Z2dlc3Rpb25zIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBIRUxQRVIgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEdlbmVyYXRlIHRpbWluZyBzdWdnZXN0aW9ucyBiYXNlZCBvbiBtYXJrZXQgcGFyYW1ldGVyc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVUaW1pbmdTdWdnZXN0aW9ucyhwYXJhbXM6IE1hcmtldFRpbWluZ1BhcmFtcyk6IHN0cmluZ1tdIHtcbiAgY29uc3Qgc3VnZ2VzdGlvbnM6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG5cbiAgaWYgKHBhcmFtcy5tYXJrZXRUeXBlID09PSAnZXZlbnQnICYmIHBhcmFtcy5ldmVudFRpbWUpIHtcbiAgICAvLyBTdWdnZXN0IGNsb3NpbmcgdGltZSBmb3IgZXZlbnQtYmFzZWQgbWFya2V0c1xuICAgIGNvbnN0IG9wdGltYWxDbG9zZSA9IG5ldyBEYXRlKFxuICAgICAgcGFyYW1zLmV2ZW50VGltZS5nZXRUaW1lKCkgLSBUSU1JTkcuUkVDT01NRU5ERURfRVZFTlRfQlVGRkVSX0hPVVJTICogNjAgKiA2MCAqIDEwMDBcbiAgICApO1xuXG4gICAgaWYgKG9wdGltYWxDbG9zZSA+IG5vdykge1xuICAgICAgc3VnZ2VzdGlvbnMucHVzaChgT3B0aW1hbCBiZXR0aW5nIGNsb3NlOiAke29wdGltYWxDbG9zZS50b0lTT1N0cmluZygpfWApO1xuICAgIH1cblxuICAgIC8vIFN1Z2dlc3QgcXVlc3Rpb24gZm9ybWF0XG4gICAgaWYgKCFwYXJhbXMucXVlc3Rpb24uaW5jbHVkZXMoJz8nKSkge1xuICAgICAgc3VnZ2VzdGlvbnMucHVzaCgnRW5kIHlvdXIgcXVlc3Rpb24gd2l0aCBcIj9cIiBmb3IgY2xhcml0eScpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChwYXJhbXMubWFya2V0VHlwZSA9PT0gJ21lYXN1cmVtZW50JyAmJiBwYXJhbXMubWVhc3VyZW1lbnRTdGFydCkge1xuICAgIC8vIFN1Z2dlc3QgY2xvc2luZyB0aW1lIGZvciBtZWFzdXJlbWVudCBtYXJrZXRzXG4gICAgY29uc3Qgb3B0aW1hbENsb3NlID0gbmV3IERhdGUoXG4gICAgICBwYXJhbXMubWVhc3VyZW1lbnRTdGFydC5nZXRUaW1lKCkgLSAyICogNjAgKiA2MCAqIDEwMDBcbiAgICApO1xuXG4gICAgaWYgKG9wdGltYWxDbG9zZSA+IG5vdykge1xuICAgICAgc3VnZ2VzdGlvbnMucHVzaChgT3B0aW1hbCBiZXR0aW5nIGNsb3NlOiAke29wdGltYWxDbG9zZS50b0lTT1N0cmluZygpfWApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzdWdnZXN0aW9ucztcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBhIG1hcmtldCBxdWVzdGlvbiBmb2xsb3dzIGJlc3QgcHJhY3RpY2VzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVF1ZXN0aW9uRm9ybWF0KHF1ZXN0aW9uOiBzdHJpbmcpOiB7XG4gIHZhbGlkOiBib29sZWFuO1xuICBpc3N1ZXM6IHN0cmluZ1tdO1xufSB7XG4gIGNvbnN0IGlzc3Vlczogc3RyaW5nW10gPSBbXTtcblxuICAvLyBMZW5ndGggY2hlY2tzXG4gIGlmIChxdWVzdGlvbi5sZW5ndGggPCAxMCkge1xuICAgIGlzc3Vlcy5wdXNoKCdRdWVzdGlvbiB0b28gc2hvcnQgKG1pbiAxMCBjaGFycyknKTtcbiAgfVxuICBpZiAocXVlc3Rpb24ubGVuZ3RoID4gMjAwKSB7XG4gICAgaXNzdWVzLnB1c2goJ1F1ZXN0aW9uIHRvbyBsb25nIChtYXggMjAwIGNoYXJzKScpO1xuICB9XG5cbiAgLy8gRm9ybWF0IGNoZWNrc1xuICBpZiAoIXF1ZXN0aW9uLnRyaW0oKSkge1xuICAgIGlzc3Vlcy5wdXNoKCdRdWVzdGlvbiBjYW5ub3QgYmUgZW1wdHknKTtcbiAgfVxuXG4gIC8vIEJlc3QgcHJhY3RpY2UgY2hlY2tzXG4gIGlmICghcXVlc3Rpb24uaW5jbHVkZXMoJz8nKSAmJiAhcXVlc3Rpb24udG9Mb3dlckNhc2UoKS5zdGFydHNXaXRoKCd3aWxsICcpKSB7XG4gICAgaXNzdWVzLnB1c2goJ0NvbnNpZGVyIHBocmFzaW5nIGFzIGEgeWVzL25vIHF1ZXN0aW9uJyk7XG4gIH1cblxuICAvLyBDaGVjayBmb3IgYW1iaWd1b3VzIGxhbmd1YWdlXG4gIGNvbnN0IGFtYmlndW91c1Rlcm1zID0gWydtYXliZScsICdwcm9iYWJseScsICdtaWdodCcsICdjb3VsZCBwb3NzaWJseSddO1xuICBmb3IgKGNvbnN0IHRlcm0gb2YgYW1iaWd1b3VzVGVybXMpIHtcbiAgICBpZiAocXVlc3Rpb24udG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0ZXJtKSkge1xuICAgICAgaXNzdWVzLnB1c2goYEF2b2lkIGFtYmlndW91cyB0ZXJtOiBcIiR7dGVybX1cImApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdmFsaWQ6IGlzc3Vlcy5sZW5ndGggPT09IDAsXG4gICAgaXNzdWVzLFxuICB9O1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZSByZWNvbW1lbmRlZCB0aW1lcyBmb3IgYSBtYXJrZXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZVJlY29tbWVuZGVkVGltZXMoXG4gIGV2ZW50T3JNZWFzdXJlbWVudFN0YXJ0OiBEYXRlLFxuICBtYXJrZXRUeXBlOiAnZXZlbnQnIHwgJ21lYXN1cmVtZW50J1xuKToge1xuICByZWNvbW1lbmRlZENsb3NlOiBEYXRlO1xuICBsYXRlc3RDbG9zZTogRGF0ZTtcbiAgZWFybGllc3RDbG9zZTogRGF0ZTtcbn0ge1xuICBjb25zdCBidWZmZXIgPSBtYXJrZXRUeXBlID09PSAnZXZlbnQnXG4gICAgPyBUSU1JTkcuUkVDT01NRU5ERURfRVZFTlRfQlVGRkVSX0hPVVJTICogNjAgKiA2MCAqIDEwMDBcbiAgICA6IDIgKiA2MCAqIDYwICogMTAwMDsgLy8gMiBob3VycyBmb3IgbWVhc3VyZW1lbnRcblxuICBjb25zdCBtaW5CdWZmZXIgPSBtYXJrZXRUeXBlID09PSAnZXZlbnQnXG4gICAgPyBUSU1JTkcuTUlOX0VWRU5UX0JVRkZFUl9IT1VSUyAqIDYwICogNjAgKiAxMDAwXG4gICAgOiAxICogNjAgKiA2MCAqIDEwMDA7IC8vIDEgaG91ciBmb3IgbWVhc3VyZW1lbnRcblxuICBjb25zdCBtYXhCdWZmZXIgPSA0OCAqIDYwICogNjAgKiAxMDAwOyAvLyA0OCBob3VycyBtYXhcblxuICByZXR1cm4ge1xuICAgIHJlY29tbWVuZGVkQ2xvc2U6IG5ldyBEYXRlKGV2ZW50T3JNZWFzdXJlbWVudFN0YXJ0LmdldFRpbWUoKSAtIGJ1ZmZlciksXG4gICAgbGF0ZXN0Q2xvc2U6IG5ldyBEYXRlKGV2ZW50T3JNZWFzdXJlbWVudFN0YXJ0LmdldFRpbWUoKSAtIG1pbkJ1ZmZlciksXG4gICAgZWFybGllc3RDbG9zZTogbmV3IERhdGUoZXZlbnRPck1lYXN1cmVtZW50U3RhcnQuZ2V0VGltZSgpIC0gbWF4QnVmZmVyKSxcbiAgfTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BAOZI PARIMUTUEL MARKET RULES v6.2
|
|
3
|
+
*
|
|
4
|
+
* STRICT ENFORCEMENT - All Lab markets MUST comply with these rules.
|
|
5
|
+
* AI agents creating markets through MCP MUST validate against these rules.
|
|
6
|
+
* Markets that don't comply will be BLOCKED from creation.
|
|
7
|
+
*/
|
|
8
|
+
export declare const PARIMUTUEL_RULES: {
|
|
9
|
+
version: string;
|
|
10
|
+
/**
|
|
11
|
+
* RULE A: Event-Based Markets
|
|
12
|
+
*
|
|
13
|
+
* For markets about specific events (sports, elections, announcements):
|
|
14
|
+
* - Betting must close AT LEAST 12 hours BEFORE the event
|
|
15
|
+
* - Recommended buffer: 18-24 hours
|
|
16
|
+
* - Event time must be explicitly specified
|
|
17
|
+
*
|
|
18
|
+
* RATIONALE: Prevents late-breaking information from giving unfair advantage
|
|
19
|
+
*
|
|
20
|
+
* Examples:
|
|
21
|
+
* ✅ "Will Team A win vs Team B?" + event_time = game_start
|
|
22
|
+
* ✅ "Will Company X announce earnings above $1B?" + event_time = announcement
|
|
23
|
+
* ❌ "Will it rain tomorrow?" (no clear event time)
|
|
24
|
+
*/
|
|
25
|
+
RULE_A: {
|
|
26
|
+
name: string;
|
|
27
|
+
minBufferHours: number;
|
|
28
|
+
recommendedBufferHours: number;
|
|
29
|
+
requirement: string;
|
|
30
|
+
rationale: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* RULE B: Measurement-Period Markets
|
|
34
|
+
*
|
|
35
|
+
* For markets about measured values (prices, temperatures, metrics):
|
|
36
|
+
* - Betting must close BEFORE the measurement period starts
|
|
37
|
+
* - measurement_start must be explicitly specified
|
|
38
|
+
* - Recommended: betting closes 1-2 hours before measurement
|
|
39
|
+
*
|
|
40
|
+
* RATIONALE: Prevents anyone from betting with foreknowledge of measurements
|
|
41
|
+
*
|
|
42
|
+
* Examples:
|
|
43
|
+
* ✅ "Will BTC be above $100k at 00:00 UTC Feb 1?" + measurement_start = Feb 1 00:00
|
|
44
|
+
* ✅ "Will Tokyo have snowfall on Feb 4?" + measurement_start = Feb 4 00:00
|
|
45
|
+
* ❌ "Will BTC close above $100k on Feb 2?" + betting_closes = Feb 2 23:59 (VIOLATION!)
|
|
46
|
+
*/
|
|
47
|
+
RULE_B: {
|
|
48
|
+
name: string;
|
|
49
|
+
requirement: string;
|
|
50
|
+
rationale: string;
|
|
51
|
+
recommendedBufferHours: number;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* MANDATORY: Verifiable Data Source
|
|
55
|
+
*
|
|
56
|
+
* Every market question MUST specify or clearly imply a verifiable data source.
|
|
57
|
+
* This ensures objective resolution and prevents disputes.
|
|
58
|
+
*
|
|
59
|
+
* Examples:
|
|
60
|
+
* ✅ "Will BTC be above $100k? (Source: CoinGecko)"
|
|
61
|
+
* ✅ "Will it snow in Tokyo? (JMA official record)"
|
|
62
|
+
* ✅ "Will Real Madrid win?" (Implied: official UEFA result)
|
|
63
|
+
* ❌ "Will the economy improve?" (No verifiable source)
|
|
64
|
+
* ❌ "Will Claude be the best AI?" (Subjective, no source)
|
|
65
|
+
*/
|
|
66
|
+
DATA_SOURCE: {
|
|
67
|
+
name: string;
|
|
68
|
+
requirement: string;
|
|
69
|
+
rationale: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* MANDATORY: Clear YES/NO Criteria
|
|
73
|
+
*
|
|
74
|
+
* The market question must have clear, unambiguous YES/NO criteria.
|
|
75
|
+
* There should be no room for interpretation in the resolution.
|
|
76
|
+
*
|
|
77
|
+
* Examples:
|
|
78
|
+
* ✅ "Will BTC be above $100,000 at 00:00 UTC Feb 1, 2026?"
|
|
79
|
+
* ✅ "Will Team A score 3+ goals?"
|
|
80
|
+
* ❌ "Will BTC perform well?" (Subjective)
|
|
81
|
+
* ❌ "Will the game be exciting?" (Subjective)
|
|
82
|
+
*/
|
|
83
|
+
CLEAR_CRITERIA: {
|
|
84
|
+
name: string;
|
|
85
|
+
requirement: string;
|
|
86
|
+
rationale: string;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
export interface ParimutuelValidationResult {
|
|
90
|
+
valid: boolean;
|
|
91
|
+
blocked: boolean;
|
|
92
|
+
errors: string[];
|
|
93
|
+
warnings: string[];
|
|
94
|
+
ruleViolations: {
|
|
95
|
+
rule: string;
|
|
96
|
+
description: string;
|
|
97
|
+
severity: 'CRITICAL' | 'ERROR' | 'WARNING';
|
|
98
|
+
}[];
|
|
99
|
+
rulesChecked: string[];
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Validate market against parimutuel rules
|
|
103
|
+
* Returns BLOCKED=true if market violates mandatory rules
|
|
104
|
+
*/
|
|
105
|
+
export declare function validateParimutuelRules(params: {
|
|
106
|
+
question: string;
|
|
107
|
+
closingTime: Date;
|
|
108
|
+
marketType?: 'event' | 'measurement';
|
|
109
|
+
eventTime?: Date;
|
|
110
|
+
measurementStart?: Date;
|
|
111
|
+
layer: 'official' | 'lab' | 'private';
|
|
112
|
+
}): ParimutuelValidationResult;
|
|
113
|
+
export declare const PARIMUTUEL_RULES_DOCUMENTATION = "\n# BAOZI PARIMUTUEL MARKET RULES v6.2\n\n## MANDATORY FOR ALL LAB MARKETS\n\n### Rule A: Event-Based Markets\nMarkets about specific events (sports, elections, announcements):\n- Betting MUST close AT LEAST 12 hours BEFORE the event\n- You MUST specify event_time parameter\n- Recommended buffer: 18-24 hours\n\nExample:\n- Question: \"Will Team A win vs Team B?\"\n- Event time: Game start (e.g., 2026-02-15T20:00:00Z)\n- Closing time: At least 12h before (e.g., 2026-02-15T08:00:00Z)\n\n### Rule B: Measurement-Period Markets\nMarkets about measured values (prices, temperatures, metrics):\n- Betting MUST close BEFORE the measurement period starts\n- You MUST specify measurement_start parameter\n- Recommended: betting closes 1-2 hours before measurement\n\nExample:\n- Question: \"Will BTC be above $100k at 00:00 UTC Feb 1?\"\n- Measurement start: 2026-02-01T00:00:00Z\n- Closing time: BEFORE measurement (e.g., 2026-01-31T22:00:00Z)\n\n### Data Source Requirement\n- Include verifiable data source in question\n- Examples: \"(Source: CoinGecko)\", \"(Official: UEFA)\", \"(NWS Los Angeles)\"\n\n### Clear Criteria\n- Question must have unambiguous YES/NO resolution\n- Include specific thresholds: \"$100,000\", \"3+ goals\", etc.\n\n## VIOLATIONS WILL BLOCK MARKET CREATION\n\nIf you try to create a market that violates these rules, the MCP will:\n1. Return blocked: true\n2. List specific rule violations\n3. Refuse to build the transaction\n\n## CLASSIFICATION REQUIRED\n\nEvery Lab market MUST be classified as either:\n1. Event-based (provide event_time) - Rule A applies\n2. Measurement-based (provide measurement_start) - Rule B applies\n\nUnclassified markets will be BLOCKED.\n";
|
|
114
|
+
/**
|
|
115
|
+
* Get rules summary for AI agents
|
|
116
|
+
*/
|
|
117
|
+
export declare function getParimutuelRulesSummary(): string;
|