pmxtjs 1.5.7 → 1.7.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/dist/esm/generated/src/models/MarketOutcome.d.ts +8 -1
- package/dist/esm/generated/src/models/MarketOutcome.js +2 -0
- package/dist/esm/generated/src/models/UnifiedMarket.d.ts +8 -1
- package/dist/esm/generated/src/models/UnifiedMarket.js +2 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/pmxt/client.d.ts +46 -1
- package/dist/esm/pmxt/client.js +242 -0
- package/dist/esm/pmxt/models.d.ts +82 -0
- package/dist/esm/pmxt/server-manager.d.ts +8 -0
- package/dist/esm/pmxt/server-manager.js +13 -0
- package/dist/generated/src/models/MarketOutcome.d.ts +8 -1
- package/dist/generated/src/models/MarketOutcome.js +2 -0
- package/dist/generated/src/models/UnifiedMarket.d.ts +8 -1
- package/dist/generated/src/models/UnifiedMarket.js +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +9 -0
- package/dist/pmxt/client.d.ts +46 -1
- package/dist/pmxt/client.js +242 -0
- package/dist/pmxt/models.d.ts +82 -0
- package/dist/pmxt/server-manager.d.ts +8 -0
- package/dist/pmxt/server-manager.js +13 -0
- package/generated/docs/MarketOutcome.md +2 -0
- package/generated/docs/UnifiedMarket.md +2 -0
- package/generated/package.json +1 -1
- package/generated/src/models/MarketOutcome.ts +10 -1
- package/generated/src/models/UnifiedMarket.ts +10 -1
- package/index.ts +12 -0
- package/package.json +2 -2
- package/pmxt/client.ts +286 -0
- package/pmxt/models.ts +88 -1
- package/pmxt/server-manager.ts +15 -0
package/pmxt/client.ts
CHANGED
|
@@ -37,6 +37,10 @@ import {
|
|
|
37
37
|
SearchIn,
|
|
38
38
|
UnifiedEvent,
|
|
39
39
|
ExecutionPriceResult,
|
|
40
|
+
MarketFilterCriteria,
|
|
41
|
+
MarketFilterFunction,
|
|
42
|
+
EventFilterCriteria,
|
|
43
|
+
EventFilterFunction,
|
|
40
44
|
} from "./models.js";
|
|
41
45
|
|
|
42
46
|
import { ServerManager } from "./server-manager.js";
|
|
@@ -935,6 +939,288 @@ export abstract class Exchange {
|
|
|
935
939
|
throw new Error(`Failed to get execution price: ${error}`);
|
|
936
940
|
}
|
|
937
941
|
}
|
|
942
|
+
|
|
943
|
+
// ----------------------------------------------------------------------------
|
|
944
|
+
// Filtering Methods
|
|
945
|
+
// ----------------------------------------------------------------------------
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* Filter markets based on criteria or custom function.
|
|
949
|
+
*
|
|
950
|
+
* @param markets - Array of markets to filter
|
|
951
|
+
* @param criteria - Filter criteria object, string (simple text search), or predicate function
|
|
952
|
+
* @returns Filtered array of markets
|
|
953
|
+
*
|
|
954
|
+
* @example Simple text search
|
|
955
|
+
* api.filterMarkets(markets, 'Trump')
|
|
956
|
+
*
|
|
957
|
+
* @example Advanced filtering
|
|
958
|
+
* api.filterMarkets(markets, {
|
|
959
|
+
* text: 'Trump',
|
|
960
|
+
* searchIn: ['title', 'tags'],
|
|
961
|
+
* volume24h: { min: 10000 },
|
|
962
|
+
* category: 'Politics',
|
|
963
|
+
* price: { outcome: 'yes', max: 0.5 }
|
|
964
|
+
* })
|
|
965
|
+
*
|
|
966
|
+
* @example Custom predicate
|
|
967
|
+
* api.filterMarkets(markets, m => m.liquidity > 5000 && m.yes?.price < 0.3)
|
|
968
|
+
*/
|
|
969
|
+
filterMarkets(
|
|
970
|
+
markets: UnifiedMarket[],
|
|
971
|
+
criteria: string | MarketFilterCriteria | MarketFilterFunction
|
|
972
|
+
): UnifiedMarket[] {
|
|
973
|
+
// Handle predicate function
|
|
974
|
+
if (typeof criteria === 'function') {
|
|
975
|
+
return markets.filter(criteria);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// Handle simple string search
|
|
979
|
+
if (typeof criteria === 'string') {
|
|
980
|
+
const lowerQuery = criteria.toLowerCase();
|
|
981
|
+
return markets.filter(m =>
|
|
982
|
+
m.title.toLowerCase().includes(lowerQuery)
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// Handle criteria object
|
|
987
|
+
return markets.filter(market => {
|
|
988
|
+
// Text search
|
|
989
|
+
if (criteria.text) {
|
|
990
|
+
const lowerQuery = criteria.text.toLowerCase();
|
|
991
|
+
const searchIn = criteria.searchIn || ['title'];
|
|
992
|
+
let textMatch = false;
|
|
993
|
+
|
|
994
|
+
for (const field of searchIn) {
|
|
995
|
+
if (field === 'title' && market.title?.toLowerCase().includes(lowerQuery)) {
|
|
996
|
+
textMatch = true;
|
|
997
|
+
break;
|
|
998
|
+
}
|
|
999
|
+
if (field === 'description' && market.description?.toLowerCase().includes(lowerQuery)) {
|
|
1000
|
+
textMatch = true;
|
|
1001
|
+
break;
|
|
1002
|
+
}
|
|
1003
|
+
if (field === 'category' && market.category?.toLowerCase().includes(lowerQuery)) {
|
|
1004
|
+
textMatch = true;
|
|
1005
|
+
break;
|
|
1006
|
+
}
|
|
1007
|
+
if (field === 'tags' && market.tags?.some(tag => tag.toLowerCase().includes(lowerQuery))) {
|
|
1008
|
+
textMatch = true;
|
|
1009
|
+
break;
|
|
1010
|
+
}
|
|
1011
|
+
if (field === 'outcomes' && market.outcomes?.some(o => o.label.toLowerCase().includes(lowerQuery))) {
|
|
1012
|
+
textMatch = true;
|
|
1013
|
+
break;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
if (!textMatch) return false;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
// Category filter
|
|
1021
|
+
if (criteria.category && market.category !== criteria.category) {
|
|
1022
|
+
return false;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
// Tags filter (match ANY of the provided tags)
|
|
1026
|
+
if (criteria.tags && criteria.tags.length > 0) {
|
|
1027
|
+
const hasMatchingTag = criteria.tags.some(tag =>
|
|
1028
|
+
market.tags?.some(marketTag =>
|
|
1029
|
+
marketTag.toLowerCase() === tag.toLowerCase()
|
|
1030
|
+
)
|
|
1031
|
+
);
|
|
1032
|
+
if (!hasMatchingTag) return false;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// Volume24h filter
|
|
1036
|
+
if (criteria.volume24h) {
|
|
1037
|
+
if (criteria.volume24h.min !== undefined && market.volume24h < criteria.volume24h.min) {
|
|
1038
|
+
return false;
|
|
1039
|
+
}
|
|
1040
|
+
if (criteria.volume24h.max !== undefined && market.volume24h > criteria.volume24h.max) {
|
|
1041
|
+
return false;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
// Volume filter
|
|
1046
|
+
if (criteria.volume) {
|
|
1047
|
+
if (criteria.volume.min !== undefined && (market.volume || 0) < criteria.volume.min) {
|
|
1048
|
+
return false;
|
|
1049
|
+
}
|
|
1050
|
+
if (criteria.volume.max !== undefined && (market.volume || 0) > criteria.volume.max) {
|
|
1051
|
+
return false;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
// Liquidity filter
|
|
1056
|
+
if (criteria.liquidity) {
|
|
1057
|
+
if (criteria.liquidity.min !== undefined && market.liquidity < criteria.liquidity.min) {
|
|
1058
|
+
return false;
|
|
1059
|
+
}
|
|
1060
|
+
if (criteria.liquidity.max !== undefined && market.liquidity > criteria.liquidity.max) {
|
|
1061
|
+
return false;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// OpenInterest filter
|
|
1066
|
+
if (criteria.openInterest) {
|
|
1067
|
+
if (criteria.openInterest.min !== undefined && (market.openInterest || 0) < criteria.openInterest.min) {
|
|
1068
|
+
return false;
|
|
1069
|
+
}
|
|
1070
|
+
if (criteria.openInterest.max !== undefined && (market.openInterest || 0) > criteria.openInterest.max) {
|
|
1071
|
+
return false;
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// ResolutionDate filter
|
|
1076
|
+
if (criteria.resolutionDate && market.resolutionDate) {
|
|
1077
|
+
const resDate = market.resolutionDate;
|
|
1078
|
+
if (criteria.resolutionDate.before && resDate >= criteria.resolutionDate.before) {
|
|
1079
|
+
return false;
|
|
1080
|
+
}
|
|
1081
|
+
if (criteria.resolutionDate.after && resDate <= criteria.resolutionDate.after) {
|
|
1082
|
+
return false;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
// Price filter (for binary markets)
|
|
1087
|
+
if (criteria.price) {
|
|
1088
|
+
const outcome = market[criteria.price.outcome];
|
|
1089
|
+
if (!outcome) return false;
|
|
1090
|
+
|
|
1091
|
+
if (criteria.price.min !== undefined && outcome.price < criteria.price.min) {
|
|
1092
|
+
return false;
|
|
1093
|
+
}
|
|
1094
|
+
if (criteria.price.max !== undefined && outcome.price > criteria.price.max) {
|
|
1095
|
+
return false;
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
// Price change filter
|
|
1100
|
+
if (criteria.priceChange24h) {
|
|
1101
|
+
const outcome = market[criteria.priceChange24h.outcome];
|
|
1102
|
+
if (!outcome || outcome.priceChange24h === undefined) return false;
|
|
1103
|
+
|
|
1104
|
+
if (criteria.priceChange24h.min !== undefined && outcome.priceChange24h < criteria.priceChange24h.min) {
|
|
1105
|
+
return false;
|
|
1106
|
+
}
|
|
1107
|
+
if (criteria.priceChange24h.max !== undefined && outcome.priceChange24h > criteria.priceChange24h.max) {
|
|
1108
|
+
return false;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
return true;
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
/**
|
|
1117
|
+
* Filter events based on criteria or custom function.
|
|
1118
|
+
*
|
|
1119
|
+
* @param events - Array of events to filter
|
|
1120
|
+
* @param criteria - Filter criteria object, string (simple text search), or predicate function
|
|
1121
|
+
* @returns Filtered array of events
|
|
1122
|
+
*
|
|
1123
|
+
* @example Simple text search
|
|
1124
|
+
* api.filterEvents(events, 'Trump')
|
|
1125
|
+
*
|
|
1126
|
+
* @example Advanced filtering
|
|
1127
|
+
* api.filterEvents(events, {
|
|
1128
|
+
* text: 'Election',
|
|
1129
|
+
* searchIn: ['title', 'tags'],
|
|
1130
|
+
* category: 'Politics',
|
|
1131
|
+
* marketCount: { min: 5 }
|
|
1132
|
+
* })
|
|
1133
|
+
*
|
|
1134
|
+
* @example Custom predicate
|
|
1135
|
+
* api.filterEvents(events, e => e.markets.length > 10)
|
|
1136
|
+
*/
|
|
1137
|
+
filterEvents(
|
|
1138
|
+
events: UnifiedEvent[],
|
|
1139
|
+
criteria: string | EventFilterCriteria | EventFilterFunction
|
|
1140
|
+
): UnifiedEvent[] {
|
|
1141
|
+
// Handle predicate function
|
|
1142
|
+
if (typeof criteria === 'function') {
|
|
1143
|
+
return events.filter(criteria);
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// Handle simple string search
|
|
1147
|
+
if (typeof criteria === 'string') {
|
|
1148
|
+
const lowerQuery = criteria.toLowerCase();
|
|
1149
|
+
return events.filter(e =>
|
|
1150
|
+
e.title.toLowerCase().includes(lowerQuery)
|
|
1151
|
+
);
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
// Handle criteria object
|
|
1155
|
+
return events.filter(event => {
|
|
1156
|
+
// Text search
|
|
1157
|
+
if (criteria.text) {
|
|
1158
|
+
const lowerQuery = criteria.text.toLowerCase();
|
|
1159
|
+
const searchIn = criteria.searchIn || ['title'];
|
|
1160
|
+
let textMatch = false;
|
|
1161
|
+
|
|
1162
|
+
for (const field of searchIn) {
|
|
1163
|
+
if (field === 'title' && event.title?.toLowerCase().includes(lowerQuery)) {
|
|
1164
|
+
textMatch = true;
|
|
1165
|
+
break;
|
|
1166
|
+
}
|
|
1167
|
+
if (field === 'description' && event.description?.toLowerCase().includes(lowerQuery)) {
|
|
1168
|
+
textMatch = true;
|
|
1169
|
+
break;
|
|
1170
|
+
}
|
|
1171
|
+
if (field === 'category' && event.category?.toLowerCase().includes(lowerQuery)) {
|
|
1172
|
+
textMatch = true;
|
|
1173
|
+
break;
|
|
1174
|
+
}
|
|
1175
|
+
if (field === 'tags' && event.tags?.some(tag => tag.toLowerCase().includes(lowerQuery))) {
|
|
1176
|
+
textMatch = true;
|
|
1177
|
+
break;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
if (!textMatch) return false;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
// Category filter
|
|
1185
|
+
if (criteria.category && event.category !== criteria.category) {
|
|
1186
|
+
return false;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
// Tags filter (match ANY of the provided tags)
|
|
1190
|
+
if (criteria.tags && criteria.tags.length > 0) {
|
|
1191
|
+
const hasMatchingTag = criteria.tags.some(tag =>
|
|
1192
|
+
event.tags?.some(eventTag =>
|
|
1193
|
+
eventTag.toLowerCase() === tag.toLowerCase()
|
|
1194
|
+
)
|
|
1195
|
+
);
|
|
1196
|
+
if (!hasMatchingTag) return false;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
// Market count filter
|
|
1200
|
+
if (criteria.marketCount) {
|
|
1201
|
+
const count = event.markets.length;
|
|
1202
|
+
if (criteria.marketCount.min !== undefined && count < criteria.marketCount.min) {
|
|
1203
|
+
return false;
|
|
1204
|
+
}
|
|
1205
|
+
if (criteria.marketCount.max !== undefined && count > criteria.marketCount.max) {
|
|
1206
|
+
return false;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// Total volume filter
|
|
1211
|
+
if (criteria.totalVolume) {
|
|
1212
|
+
const totalVolume = event.markets.reduce((sum, m) => sum + m.volume24h, 0);
|
|
1213
|
+
if (criteria.totalVolume.min !== undefined && totalVolume < criteria.totalVolume.min) {
|
|
1214
|
+
return false;
|
|
1215
|
+
}
|
|
1216
|
+
if (criteria.totalVolume.max !== undefined && totalVolume > criteria.totalVolume.max) {
|
|
1217
|
+
return false;
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
return true;
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
938
1224
|
}
|
|
939
1225
|
|
|
940
1226
|
/**
|
package/pmxt/models.ts
CHANGED
|
@@ -352,10 +352,97 @@ export interface UnifiedEvent {
|
|
|
352
352
|
|
|
353
353
|
/**
|
|
354
354
|
* Search for markets within this event by keyword.
|
|
355
|
-
*
|
|
355
|
+
*
|
|
356
356
|
* @param query - Search query (case-insensitive)
|
|
357
357
|
* @param searchIn - Where to search - "title", "description", or "both"
|
|
358
358
|
* @returns List of matching markets
|
|
359
359
|
*/
|
|
360
360
|
searchMarkets(query: string, searchIn?: SearchIn): UnifiedMarket[];
|
|
361
361
|
}
|
|
362
|
+
|
|
363
|
+
// ----------------------------------------------------------------------------
|
|
364
|
+
// Advanced Filtering Types
|
|
365
|
+
// ----------------------------------------------------------------------------
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Advanced criteria for filtering markets.
|
|
369
|
+
* Supports text search, numeric ranges, dates, categories, and price filters.
|
|
370
|
+
*/
|
|
371
|
+
export interface MarketFilterCriteria {
|
|
372
|
+
/** Text search query */
|
|
373
|
+
text?: string;
|
|
374
|
+
|
|
375
|
+
/** Fields to search in (default: ['title']) */
|
|
376
|
+
searchIn?: ('title' | 'description' | 'category' | 'tags' | 'outcomes')[];
|
|
377
|
+
|
|
378
|
+
/** Filter by 24-hour volume */
|
|
379
|
+
volume24h?: { min?: number; max?: number };
|
|
380
|
+
|
|
381
|
+
/** Filter by total volume */
|
|
382
|
+
volume?: { min?: number; max?: number };
|
|
383
|
+
|
|
384
|
+
/** Filter by liquidity */
|
|
385
|
+
liquidity?: { min?: number; max?: number };
|
|
386
|
+
|
|
387
|
+
/** Filter by open interest */
|
|
388
|
+
openInterest?: { min?: number; max?: number };
|
|
389
|
+
|
|
390
|
+
/** Filter by resolution date */
|
|
391
|
+
resolutionDate?: {
|
|
392
|
+
before?: Date;
|
|
393
|
+
after?: Date;
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
/** Filter by category */
|
|
397
|
+
category?: string;
|
|
398
|
+
|
|
399
|
+
/** Filter by tags (matches if market has ANY of these) */
|
|
400
|
+
tags?: string[];
|
|
401
|
+
|
|
402
|
+
/** Filter by outcome price (for binary markets) */
|
|
403
|
+
price?: {
|
|
404
|
+
outcome: 'yes' | 'no' | 'up' | 'down';
|
|
405
|
+
min?: number;
|
|
406
|
+
max?: number;
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
/** Filter by 24-hour price change */
|
|
410
|
+
priceChange24h?: {
|
|
411
|
+
outcome: 'yes' | 'no' | 'up' | 'down';
|
|
412
|
+
min?: number;
|
|
413
|
+
max?: number;
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Function type for custom market filtering logic.
|
|
419
|
+
*/
|
|
420
|
+
export type MarketFilterFunction = (market: UnifiedMarket) => boolean;
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Advanced criteria for filtering events.
|
|
424
|
+
*/
|
|
425
|
+
export interface EventFilterCriteria {
|
|
426
|
+
/** Text search query */
|
|
427
|
+
text?: string;
|
|
428
|
+
|
|
429
|
+
/** Fields to search in (default: ['title']) */
|
|
430
|
+
searchIn?: ('title' | 'description' | 'category' | 'tags')[];
|
|
431
|
+
|
|
432
|
+
/** Filter by category */
|
|
433
|
+
category?: string;
|
|
434
|
+
|
|
435
|
+
/** Filter by tags (matches if event has ANY of these) */
|
|
436
|
+
tags?: string[];
|
|
437
|
+
|
|
438
|
+
/** Filter by number of markets in the event */
|
|
439
|
+
marketCount?: { min?: number; max?: number };
|
|
440
|
+
|
|
441
|
+
/** Filter by total volume across all markets */
|
|
442
|
+
totalVolume?: { min?: number; max?: number };
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Function type for custom event filtering logic.
|
|
447
|
+
*/
|
|
448
|
+
export type EventFilterFunction = (event: UnifiedEvent) => boolean;
|
package/pmxt/server-manager.ts
CHANGED
|
@@ -203,6 +203,21 @@ export class ServerManager {
|
|
|
203
203
|
return false;
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Stop the currently running server.
|
|
208
|
+
*/
|
|
209
|
+
async stop(): Promise<void> {
|
|
210
|
+
await this.killOldServer();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Restart the server.
|
|
215
|
+
*/
|
|
216
|
+
async restart(): Promise<void> {
|
|
217
|
+
await this.stop();
|
|
218
|
+
await this.ensureServerRunning();
|
|
219
|
+
}
|
|
220
|
+
|
|
206
221
|
private async killOldServer(): Promise<void> {
|
|
207
222
|
const info = this.getServerInfo();
|
|
208
223
|
if (info && info.pid) {
|