pmxtjs 2.43.19 → 2.43.24
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/Order.d.ts +1 -1
- package/dist/esm/generated/src/models/Order.js +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/pmxt/args.d.ts +1 -1
- package/dist/esm/pmxt/client.js +4 -1
- package/dist/esm/pmxt/errors.d.ts +2 -2
- package/dist/esm/pmxt/errors.js +14 -14
- package/dist/esm/pmxt/feed-client.d.ts +2 -2
- package/dist/esm/pmxt/feed-client.js +5 -2
- package/dist/esm/pmxt/logger.d.ts +18 -0
- package/dist/esm/pmxt/logger.js +74 -0
- package/dist/esm/pmxt/models.d.ts +2 -2
- package/dist/esm/pmxt/router.js +3 -1
- package/dist/esm/pmxt/server-manager.js +6 -2
- package/dist/esm/pmxt/ws-client.js +21 -2
- package/dist/generated/src/models/Order.d.ts +1 -1
- package/dist/generated/src/models/Order.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/pmxt/args.d.ts +1 -1
- package/dist/pmxt/client.js +4 -1
- package/dist/pmxt/errors.d.ts +2 -2
- package/dist/pmxt/errors.js +14 -14
- package/dist/pmxt/feed-client.d.ts +2 -2
- package/dist/pmxt/feed-client.js +5 -2
- package/dist/pmxt/logger.d.ts +18 -0
- package/dist/pmxt/logger.js +77 -0
- package/dist/pmxt/models.d.ts +2 -2
- package/dist/pmxt/router.js +3 -1
- package/dist/pmxt/server-manager.js +6 -2
- package/dist/pmxt/ws-client.js +21 -2
- package/generated/package.json +1 -1
- package/generated/src/models/Order.ts +1 -1
- package/package.json +2 -2
- package/pmxt/args.ts +1 -1
- package/pmxt/client.ts +4 -1
- package/pmxt/errors.ts +16 -15
- package/pmxt/feed-client.ts +7 -4
- package/pmxt/logger.ts +78 -0
- package/pmxt/models.ts +2 -2
- package/pmxt/router.ts +3 -1
- package/pmxt/server-manager.ts +6 -2
- package/pmxt/ws-client.ts +21 -4
|
@@ -123,7 +123,7 @@ export declare const OrderStatusEnum: {
|
|
|
123
123
|
readonly Pending: "pending";
|
|
124
124
|
readonly Open: "open";
|
|
125
125
|
readonly Filled: "filled";
|
|
126
|
-
readonly
|
|
126
|
+
readonly Canceled: "canceled";
|
|
127
127
|
readonly Rejected: "rejected";
|
|
128
128
|
};
|
|
129
129
|
export type OrderStatusEnum = typeof OrderStatusEnum[keyof typeof OrderStatusEnum];
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ export declare const server: {
|
|
|
57
57
|
readonly logs: (n?: number) => string[];
|
|
58
58
|
};
|
|
59
59
|
declare const pmxt: {
|
|
60
|
-
fromServerError(errorData:
|
|
60
|
+
fromServerError(errorData: unknown): errors.PmxtError;
|
|
61
61
|
PmxtError: typeof errors.PmxtError;
|
|
62
62
|
BadRequest: typeof errors.BadRequest;
|
|
63
63
|
AuthenticationError: typeof errors.AuthenticationError;
|
package/dist/esm/pmxt/args.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function buildArgsWithOptionalOptions(primary?:
|
|
1
|
+
export declare function buildArgsWithOptionalOptions<T>(primary?: T): T[];
|
package/dist/esm/pmxt/client.js
CHANGED
|
@@ -270,7 +270,10 @@ export class Exchange {
|
|
|
270
270
|
let lastError;
|
|
271
271
|
for (let attempt = 0; attempt <= delays.length; attempt++) {
|
|
272
272
|
try {
|
|
273
|
-
return await fetch(input,
|
|
273
|
+
return await fetch(input, {
|
|
274
|
+
...init,
|
|
275
|
+
signal: AbortSignal.timeout(30_000),
|
|
276
|
+
});
|
|
274
277
|
}
|
|
275
278
|
catch (error) {
|
|
276
279
|
lastError = error;
|
|
@@ -20,7 +20,7 @@ export declare class PermissionDenied extends PmxtError {
|
|
|
20
20
|
constructor(message: string, exchange?: string);
|
|
21
21
|
}
|
|
22
22
|
export declare class NotFoundError extends PmxtError {
|
|
23
|
-
constructor(message: string, exchange?: string);
|
|
23
|
+
constructor(message: string, exchange?: string, code?: string);
|
|
24
24
|
}
|
|
25
25
|
export declare class OrderNotFound extends NotFoundError {
|
|
26
26
|
constructor(orderId: string, exchange?: string);
|
|
@@ -52,4 +52,4 @@ export declare class ExchangeNotAvailable extends PmxtError {
|
|
|
52
52
|
constructor(message: string, exchange?: string);
|
|
53
53
|
}
|
|
54
54
|
/** Convert a server error response object into a typed PmxtError. */
|
|
55
|
-
export declare function fromServerError(errorData:
|
|
55
|
+
export declare function fromServerError(errorData: unknown): PmxtError;
|
package/dist/esm/pmxt/errors.js
CHANGED
|
@@ -36,26 +36,23 @@ export class PermissionDenied extends PmxtError {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
export class NotFoundError extends PmxtError {
|
|
39
|
-
constructor(message, exchange) {
|
|
40
|
-
super(message,
|
|
39
|
+
constructor(message, exchange, code = "NOT_FOUND") {
|
|
40
|
+
super(message, code, false, exchange);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
export class OrderNotFound extends NotFoundError {
|
|
44
44
|
constructor(orderId, exchange) {
|
|
45
|
-
super(`Order not found: ${orderId}`, exchange);
|
|
46
|
-
this.code = "ORDER_NOT_FOUND";
|
|
45
|
+
super(`Order not found: ${orderId}`, exchange, "ORDER_NOT_FOUND");
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
export class MarketNotFound extends NotFoundError {
|
|
50
49
|
constructor(marketId, exchange) {
|
|
51
|
-
super(`Market not found: ${marketId}`, exchange);
|
|
52
|
-
this.code = "MARKET_NOT_FOUND";
|
|
50
|
+
super(`Market not found: ${marketId}`, exchange, "MARKET_NOT_FOUND");
|
|
53
51
|
}
|
|
54
52
|
}
|
|
55
53
|
export class EventNotFound extends NotFoundError {
|
|
56
54
|
constructor(identifier, exchange) {
|
|
57
|
-
super(`Event not found: ${identifier}`, exchange);
|
|
58
|
-
this.code = "EVENT_NOT_FOUND";
|
|
55
|
+
super(`Event not found: ${identifier}`, exchange, "EVENT_NOT_FOUND");
|
|
59
56
|
}
|
|
60
57
|
}
|
|
61
58
|
export class RateLimitExceeded extends PmxtError {
|
|
@@ -114,16 +111,19 @@ export function fromServerError(errorData) {
|
|
|
114
111
|
if (typeof errorData === "string") {
|
|
115
112
|
return new PmxtError(errorData);
|
|
116
113
|
}
|
|
117
|
-
const
|
|
118
|
-
const
|
|
119
|
-
const
|
|
120
|
-
const
|
|
114
|
+
const data = errorData;
|
|
115
|
+
const message = (typeof data.message === "string" ? data.message : undefined) || "Unknown error";
|
|
116
|
+
const code = (typeof data.code === "string" ? data.code : undefined) || "UNKNOWN_ERROR";
|
|
117
|
+
const retryable = typeof data.retryable === "boolean" ? data.retryable : false;
|
|
118
|
+
const exchange = typeof data.exchange === "string" ? data.exchange : undefined;
|
|
121
119
|
const ErrorClass = ERROR_CODE_MAP[code];
|
|
122
120
|
if (ErrorClass === RateLimitExceeded) {
|
|
123
|
-
|
|
121
|
+
const retryAfter = typeof data.retryAfter === "number" ? data.retryAfter : undefined;
|
|
122
|
+
return new RateLimitExceeded(message, retryAfter, exchange);
|
|
124
123
|
}
|
|
125
124
|
if (ErrorClass === ValidationError) {
|
|
126
|
-
|
|
125
|
+
const field = typeof data.field === "string" ? data.field : undefined;
|
|
126
|
+
return new ValidationError(message, field, exchange);
|
|
127
127
|
}
|
|
128
128
|
if (ErrorClass) {
|
|
129
129
|
return new ErrorClass(message, exchange);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export interface Ticker {
|
|
9
9
|
symbol: string;
|
|
10
|
-
info:
|
|
10
|
+
info: Record<string, unknown>;
|
|
11
11
|
timestamp: number | undefined;
|
|
12
12
|
datetime: string | undefined;
|
|
13
13
|
high: number | undefined;
|
|
@@ -38,7 +38,7 @@ export interface Market {
|
|
|
38
38
|
quote: string;
|
|
39
39
|
active: boolean;
|
|
40
40
|
type: string;
|
|
41
|
-
info:
|
|
41
|
+
info: Record<string, unknown>;
|
|
42
42
|
}
|
|
43
43
|
export interface OracleRound {
|
|
44
44
|
feed: string;
|
|
@@ -34,7 +34,7 @@ export class FeedClient {
|
|
|
34
34
|
params.symbols = symbols.join(',');
|
|
35
35
|
return this.get('fetchTickers', params);
|
|
36
36
|
}
|
|
37
|
-
async fetchOHLCV(symbol, timeframe, since, limit) {
|
|
37
|
+
async fetchOHLCV(symbol, timeframe = '1h', since, limit) {
|
|
38
38
|
return this.get('fetchOHLCV', { symbol, timeframe, since, limit });
|
|
39
39
|
}
|
|
40
40
|
async fetchOracleRound(feed) {
|
|
@@ -55,7 +55,10 @@ export class FeedClient {
|
|
|
55
55
|
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)
|
|
56
56
|
.join('&');
|
|
57
57
|
const url = `${this.baseUrl}/api/feeds/${this.feedName}/${method}${qs ? '?' + qs : ''}`;
|
|
58
|
-
const response = await fetch(url, {
|
|
58
|
+
const response = await fetch(url, {
|
|
59
|
+
headers: this.headers,
|
|
60
|
+
signal: AbortSignal.timeout(30_000),
|
|
61
|
+
});
|
|
59
62
|
if (!response.ok) {
|
|
60
63
|
const body = await response.json().catch(() => ({}));
|
|
61
64
|
throw new PmxtError(body.error || response.statusText);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logger for pmxt TypeScript SDK.
|
|
3
|
+
*
|
|
4
|
+
* Thin abstraction over console that:
|
|
5
|
+
* - Attaches a `[pmxt]` prefix for easy filtering
|
|
6
|
+
* - Supports log levels (debug, info, warn, error)
|
|
7
|
+
* - Respects a configurable level threshold via PMXT_LOG_LEVEL
|
|
8
|
+
* - Can be swapped for a real transport later
|
|
9
|
+
*/
|
|
10
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
11
|
+
export declare const logger: {
|
|
12
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
13
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
14
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
15
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
16
|
+
setLevel(level: LogLevel): void;
|
|
17
|
+
getLevel(): LogLevel;
|
|
18
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logger for pmxt TypeScript SDK.
|
|
3
|
+
*
|
|
4
|
+
* Thin abstraction over console that:
|
|
5
|
+
* - Attaches a `[pmxt]` prefix for easy filtering
|
|
6
|
+
* - Supports log levels (debug, info, warn, error)
|
|
7
|
+
* - Respects a configurable level threshold via PMXT_LOG_LEVEL
|
|
8
|
+
* - Can be swapped for a real transport later
|
|
9
|
+
*/
|
|
10
|
+
const LEVEL_PRIORITY = {
|
|
11
|
+
debug: 0,
|
|
12
|
+
info: 1,
|
|
13
|
+
warn: 2,
|
|
14
|
+
error: 3,
|
|
15
|
+
silent: 4,
|
|
16
|
+
};
|
|
17
|
+
function getDefaultLevel() {
|
|
18
|
+
if (typeof process !== 'undefined' && process.env?.PMXT_LOG_LEVEL) {
|
|
19
|
+
return process.env.PMXT_LOG_LEVEL;
|
|
20
|
+
}
|
|
21
|
+
return 'info';
|
|
22
|
+
}
|
|
23
|
+
let currentLevel = getDefaultLevel();
|
|
24
|
+
function shouldLog(level) {
|
|
25
|
+
return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[currentLevel];
|
|
26
|
+
}
|
|
27
|
+
export const logger = {
|
|
28
|
+
debug(message, context) {
|
|
29
|
+
if (!shouldLog('debug'))
|
|
30
|
+
return;
|
|
31
|
+
if (context) {
|
|
32
|
+
console.debug(`[pmxt] ${message}`, context);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
console.debug(`[pmxt] ${message}`);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
info(message, context) {
|
|
39
|
+
if (!shouldLog('info'))
|
|
40
|
+
return;
|
|
41
|
+
if (context) {
|
|
42
|
+
console.info(`[pmxt] ${message}`, context);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
console.info(`[pmxt] ${message}`);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
warn(message, context) {
|
|
49
|
+
if (!shouldLog('warn'))
|
|
50
|
+
return;
|
|
51
|
+
if (context) {
|
|
52
|
+
console.warn(`[pmxt] ${message}`, context);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.warn(`[pmxt] ${message}`);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
error(message, context) {
|
|
59
|
+
if (!shouldLog('error'))
|
|
60
|
+
return;
|
|
61
|
+
if (context) {
|
|
62
|
+
console.error(`[pmxt] ${message}`, context);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.error(`[pmxt] ${message}`);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
setLevel(level) {
|
|
69
|
+
currentLevel = level;
|
|
70
|
+
},
|
|
71
|
+
getLevel() {
|
|
72
|
+
return currentLevel;
|
|
73
|
+
},
|
|
74
|
+
};
|
|
@@ -22,7 +22,7 @@ export interface MarketOutcome {
|
|
|
22
22
|
/** 24-hour price change */
|
|
23
23
|
priceChange24h?: number;
|
|
24
24
|
/** Exchange-specific metadata */
|
|
25
|
-
metadata?: Record<string,
|
|
25
|
+
metadata?: Record<string, unknown>;
|
|
26
26
|
/** Best bid price from the order book (when includePrices=True) */
|
|
27
27
|
bestBid?: number;
|
|
28
28
|
/** Best ask price from the order book (when includePrices=True) */
|
|
@@ -201,7 +201,7 @@ export interface Trade {
|
|
|
201
201
|
side: "buy" | "sell" | "unknown";
|
|
202
202
|
}
|
|
203
203
|
/**
|
|
204
|
-
* An order (open, filled, or
|
|
204
|
+
* An order (open, filled, or canceled).
|
|
205
205
|
*/
|
|
206
206
|
export interface Order {
|
|
207
207
|
/** Order ID */
|
package/dist/esm/pmxt/router.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* every venue PMXT supports. Only requires a PMXT API key.
|
|
6
6
|
*/
|
|
7
7
|
import { Exchange } from "./client.js";
|
|
8
|
+
import { logger } from "./logger.js";
|
|
8
9
|
function convertMarket(raw) {
|
|
9
10
|
const outcomes = (raw.outcomes || []).map((o) => ({
|
|
10
11
|
outcomeId: o.outcomeId,
|
|
@@ -131,7 +132,7 @@ export class Router extends Exchange {
|
|
|
131
132
|
}
|
|
132
133
|
}
|
|
133
134
|
async fetchMatches(marketOrParams = {}) {
|
|
134
|
-
|
|
135
|
+
logger.warn('fetchMatches is deprecated, use fetchMarketMatches instead');
|
|
135
136
|
return this.fetchMarketMatches(marketOrParams);
|
|
136
137
|
}
|
|
137
138
|
async fetchEventMatches(eventOrParams = {}) {
|
|
@@ -188,6 +189,7 @@ export class Router extends Exchange {
|
|
|
188
189
|
method: 'POST',
|
|
189
190
|
headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
|
|
190
191
|
body: JSON.stringify({ args: [query], credentials: this.getCredentials() }),
|
|
192
|
+
signal: AbortSignal.timeout(30_000),
|
|
191
193
|
});
|
|
192
194
|
if (!response.ok) {
|
|
193
195
|
const body = await response.json().catch(() => ({}));
|
|
@@ -85,7 +85,9 @@ export class ServerManager {
|
|
|
85
85
|
try {
|
|
86
86
|
// Use native fetch to check health on the actual running port
|
|
87
87
|
// This avoids issues where this.api is configured with the wrong port
|
|
88
|
-
const response = await fetch(`http://localhost:${port}/health
|
|
88
|
+
const response = await fetch(`http://localhost:${port}/health`, {
|
|
89
|
+
signal: AbortSignal.timeout(5_000),
|
|
90
|
+
});
|
|
89
91
|
if (response.ok) {
|
|
90
92
|
const data = await response.json();
|
|
91
93
|
return data.status === "ok";
|
|
@@ -106,7 +108,9 @@ export class ServerManager {
|
|
|
106
108
|
const info = this.getServerInfo();
|
|
107
109
|
if (info) {
|
|
108
110
|
try {
|
|
109
|
-
const response = await fetch(`http://localhost:${info.port}/health
|
|
111
|
+
const response = await fetch(`http://localhost:${info.port}/health`, {
|
|
112
|
+
signal: AbortSignal.timeout(5_000),
|
|
113
|
+
});
|
|
110
114
|
if (response.ok) {
|
|
111
115
|
const data = await response.json();
|
|
112
116
|
if (data.status === "ok")
|
|
@@ -101,8 +101,21 @@ export class SidecarWsClient {
|
|
|
101
101
|
const raw = typeof event.data === "string"
|
|
102
102
|
? event.data
|
|
103
103
|
: event.data.toString();
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
let msg;
|
|
105
|
+
try {
|
|
106
|
+
msg = JSON.parse(raw);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Non-JSON control frame -- ignore.
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
this.dispatch(msg);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
// Dispatch bug -- log and continue; don't kill the connection.
|
|
117
|
+
console.error('[SidecarWsClient] dispatch error:', err);
|
|
118
|
+
}
|
|
106
119
|
};
|
|
107
120
|
});
|
|
108
121
|
}
|
|
@@ -188,6 +201,9 @@ export class SidecarWsClient {
|
|
|
188
201
|
if (credentials) {
|
|
189
202
|
message.credentials = credentials;
|
|
190
203
|
}
|
|
204
|
+
if (!this.ws) {
|
|
205
|
+
throw new PmxtError('[ws-client] Cannot send: WebSocket not connected');
|
|
206
|
+
}
|
|
191
207
|
this.ws.send(JSON.stringify(message));
|
|
192
208
|
return this.waitForData(requestId, timeoutMs);
|
|
193
209
|
}
|
|
@@ -213,6 +229,9 @@ export class SidecarWsClient {
|
|
|
213
229
|
if (credentials) {
|
|
214
230
|
message.credentials = credentials;
|
|
215
231
|
}
|
|
232
|
+
if (!this.ws) {
|
|
233
|
+
throw new PmxtError('[ws-client] Cannot send: WebSocket not connected');
|
|
234
|
+
}
|
|
216
235
|
this.ws.send(JSON.stringify(message));
|
|
217
236
|
// Wait for first data event
|
|
218
237
|
await this.waitForData(requestId, timeoutMs);
|
|
@@ -123,7 +123,7 @@ export declare const OrderStatusEnum: {
|
|
|
123
123
|
readonly Pending: "pending";
|
|
124
124
|
readonly Open: "open";
|
|
125
125
|
readonly Filled: "filled";
|
|
126
|
-
readonly
|
|
126
|
+
readonly Canceled: "canceled";
|
|
127
127
|
readonly Rejected: "rejected";
|
|
128
128
|
};
|
|
129
129
|
export type OrderStatusEnum = typeof OrderStatusEnum[keyof typeof OrderStatusEnum];
|
package/dist/index.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ export declare const server: {
|
|
|
57
57
|
readonly logs: (n?: number) => string[];
|
|
58
58
|
};
|
|
59
59
|
declare const pmxt: {
|
|
60
|
-
fromServerError(errorData:
|
|
60
|
+
fromServerError(errorData: unknown): errors.PmxtError;
|
|
61
61
|
PmxtError: typeof errors.PmxtError;
|
|
62
62
|
BadRequest: typeof errors.BadRequest;
|
|
63
63
|
AuthenticationError: typeof errors.AuthenticationError;
|
package/dist/pmxt/args.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function buildArgsWithOptionalOptions(primary?:
|
|
1
|
+
export declare function buildArgsWithOptionalOptions<T>(primary?: T): T[];
|
package/dist/pmxt/client.js
CHANGED
|
@@ -273,7 +273,10 @@ class Exchange {
|
|
|
273
273
|
let lastError;
|
|
274
274
|
for (let attempt = 0; attempt <= delays.length; attempt++) {
|
|
275
275
|
try {
|
|
276
|
-
return await fetch(input,
|
|
276
|
+
return await fetch(input, {
|
|
277
|
+
...init,
|
|
278
|
+
signal: AbortSignal.timeout(30_000),
|
|
279
|
+
});
|
|
277
280
|
}
|
|
278
281
|
catch (error) {
|
|
279
282
|
lastError = error;
|
package/dist/pmxt/errors.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export declare class PermissionDenied extends PmxtError {
|
|
|
20
20
|
constructor(message: string, exchange?: string);
|
|
21
21
|
}
|
|
22
22
|
export declare class NotFoundError extends PmxtError {
|
|
23
|
-
constructor(message: string, exchange?: string);
|
|
23
|
+
constructor(message: string, exchange?: string, code?: string);
|
|
24
24
|
}
|
|
25
25
|
export declare class OrderNotFound extends NotFoundError {
|
|
26
26
|
constructor(orderId: string, exchange?: string);
|
|
@@ -52,4 +52,4 @@ export declare class ExchangeNotAvailable extends PmxtError {
|
|
|
52
52
|
constructor(message: string, exchange?: string);
|
|
53
53
|
}
|
|
54
54
|
/** Convert a server error response object into a typed PmxtError. */
|
|
55
|
-
export declare function fromServerError(errorData:
|
|
55
|
+
export declare function fromServerError(errorData: unknown): PmxtError;
|
package/dist/pmxt/errors.js
CHANGED
|
@@ -44,29 +44,26 @@ class PermissionDenied extends PmxtError {
|
|
|
44
44
|
}
|
|
45
45
|
exports.PermissionDenied = PermissionDenied;
|
|
46
46
|
class NotFoundError extends PmxtError {
|
|
47
|
-
constructor(message, exchange) {
|
|
48
|
-
super(message,
|
|
47
|
+
constructor(message, exchange, code = "NOT_FOUND") {
|
|
48
|
+
super(message, code, false, exchange);
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
exports.NotFoundError = NotFoundError;
|
|
52
52
|
class OrderNotFound extends NotFoundError {
|
|
53
53
|
constructor(orderId, exchange) {
|
|
54
|
-
super(`Order not found: ${orderId}`, exchange);
|
|
55
|
-
this.code = "ORDER_NOT_FOUND";
|
|
54
|
+
super(`Order not found: ${orderId}`, exchange, "ORDER_NOT_FOUND");
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
exports.OrderNotFound = OrderNotFound;
|
|
59
58
|
class MarketNotFound extends NotFoundError {
|
|
60
59
|
constructor(marketId, exchange) {
|
|
61
|
-
super(`Market not found: ${marketId}`, exchange);
|
|
62
|
-
this.code = "MARKET_NOT_FOUND";
|
|
60
|
+
super(`Market not found: ${marketId}`, exchange, "MARKET_NOT_FOUND");
|
|
63
61
|
}
|
|
64
62
|
}
|
|
65
63
|
exports.MarketNotFound = MarketNotFound;
|
|
66
64
|
class EventNotFound extends NotFoundError {
|
|
67
65
|
constructor(identifier, exchange) {
|
|
68
|
-
super(`Event not found: ${identifier}`, exchange);
|
|
69
|
-
this.code = "EVENT_NOT_FOUND";
|
|
66
|
+
super(`Event not found: ${identifier}`, exchange, "EVENT_NOT_FOUND");
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
69
|
exports.EventNotFound = EventNotFound;
|
|
@@ -132,16 +129,19 @@ function fromServerError(errorData) {
|
|
|
132
129
|
if (typeof errorData === "string") {
|
|
133
130
|
return new PmxtError(errorData);
|
|
134
131
|
}
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
const
|
|
132
|
+
const data = errorData;
|
|
133
|
+
const message = (typeof data.message === "string" ? data.message : undefined) || "Unknown error";
|
|
134
|
+
const code = (typeof data.code === "string" ? data.code : undefined) || "UNKNOWN_ERROR";
|
|
135
|
+
const retryable = typeof data.retryable === "boolean" ? data.retryable : false;
|
|
136
|
+
const exchange = typeof data.exchange === "string" ? data.exchange : undefined;
|
|
139
137
|
const ErrorClass = ERROR_CODE_MAP[code];
|
|
140
138
|
if (ErrorClass === RateLimitExceeded) {
|
|
141
|
-
|
|
139
|
+
const retryAfter = typeof data.retryAfter === "number" ? data.retryAfter : undefined;
|
|
140
|
+
return new RateLimitExceeded(message, retryAfter, exchange);
|
|
142
141
|
}
|
|
143
142
|
if (ErrorClass === ValidationError) {
|
|
144
|
-
|
|
143
|
+
const field = typeof data.field === "string" ? data.field : undefined;
|
|
144
|
+
return new ValidationError(message, field, exchange);
|
|
145
145
|
}
|
|
146
146
|
if (ErrorClass) {
|
|
147
147
|
return new ErrorClass(message, exchange);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export interface Ticker {
|
|
9
9
|
symbol: string;
|
|
10
|
-
info:
|
|
10
|
+
info: Record<string, unknown>;
|
|
11
11
|
timestamp: number | undefined;
|
|
12
12
|
datetime: string | undefined;
|
|
13
13
|
high: number | undefined;
|
|
@@ -38,7 +38,7 @@ export interface Market {
|
|
|
38
38
|
quote: string;
|
|
39
39
|
active: boolean;
|
|
40
40
|
type: string;
|
|
41
|
-
info:
|
|
41
|
+
info: Record<string, unknown>;
|
|
42
42
|
}
|
|
43
43
|
export interface OracleRound {
|
|
44
44
|
feed: string;
|
package/dist/pmxt/feed-client.js
CHANGED
|
@@ -37,7 +37,7 @@ class FeedClient {
|
|
|
37
37
|
params.symbols = symbols.join(',');
|
|
38
38
|
return this.get('fetchTickers', params);
|
|
39
39
|
}
|
|
40
|
-
async fetchOHLCV(symbol, timeframe, since, limit) {
|
|
40
|
+
async fetchOHLCV(symbol, timeframe = '1h', since, limit) {
|
|
41
41
|
return this.get('fetchOHLCV', { symbol, timeframe, since, limit });
|
|
42
42
|
}
|
|
43
43
|
async fetchOracleRound(feed) {
|
|
@@ -58,7 +58,10 @@ class FeedClient {
|
|
|
58
58
|
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)
|
|
59
59
|
.join('&');
|
|
60
60
|
const url = `${this.baseUrl}/api/feeds/${this.feedName}/${method}${qs ? '?' + qs : ''}`;
|
|
61
|
-
const response = await fetch(url, {
|
|
61
|
+
const response = await fetch(url, {
|
|
62
|
+
headers: this.headers,
|
|
63
|
+
signal: AbortSignal.timeout(30_000),
|
|
64
|
+
});
|
|
62
65
|
if (!response.ok) {
|
|
63
66
|
const body = await response.json().catch(() => ({}));
|
|
64
67
|
throw new errors_js_1.PmxtError(body.error || response.statusText);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logger for pmxt TypeScript SDK.
|
|
3
|
+
*
|
|
4
|
+
* Thin abstraction over console that:
|
|
5
|
+
* - Attaches a `[pmxt]` prefix for easy filtering
|
|
6
|
+
* - Supports log levels (debug, info, warn, error)
|
|
7
|
+
* - Respects a configurable level threshold via PMXT_LOG_LEVEL
|
|
8
|
+
* - Can be swapped for a real transport later
|
|
9
|
+
*/
|
|
10
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
11
|
+
export declare const logger: {
|
|
12
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
13
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
14
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
15
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
16
|
+
setLevel(level: LogLevel): void;
|
|
17
|
+
getLevel(): LogLevel;
|
|
18
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Structured logger for pmxt TypeScript SDK.
|
|
4
|
+
*
|
|
5
|
+
* Thin abstraction over console that:
|
|
6
|
+
* - Attaches a `[pmxt]` prefix for easy filtering
|
|
7
|
+
* - Supports log levels (debug, info, warn, error)
|
|
8
|
+
* - Respects a configurable level threshold via PMXT_LOG_LEVEL
|
|
9
|
+
* - Can be swapped for a real transport later
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.logger = void 0;
|
|
13
|
+
const LEVEL_PRIORITY = {
|
|
14
|
+
debug: 0,
|
|
15
|
+
info: 1,
|
|
16
|
+
warn: 2,
|
|
17
|
+
error: 3,
|
|
18
|
+
silent: 4,
|
|
19
|
+
};
|
|
20
|
+
function getDefaultLevel() {
|
|
21
|
+
if (typeof process !== 'undefined' && process.env?.PMXT_LOG_LEVEL) {
|
|
22
|
+
return process.env.PMXT_LOG_LEVEL;
|
|
23
|
+
}
|
|
24
|
+
return 'info';
|
|
25
|
+
}
|
|
26
|
+
let currentLevel = getDefaultLevel();
|
|
27
|
+
function shouldLog(level) {
|
|
28
|
+
return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[currentLevel];
|
|
29
|
+
}
|
|
30
|
+
exports.logger = {
|
|
31
|
+
debug(message, context) {
|
|
32
|
+
if (!shouldLog('debug'))
|
|
33
|
+
return;
|
|
34
|
+
if (context) {
|
|
35
|
+
console.debug(`[pmxt] ${message}`, context);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
console.debug(`[pmxt] ${message}`);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
info(message, context) {
|
|
42
|
+
if (!shouldLog('info'))
|
|
43
|
+
return;
|
|
44
|
+
if (context) {
|
|
45
|
+
console.info(`[pmxt] ${message}`, context);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
console.info(`[pmxt] ${message}`);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
warn(message, context) {
|
|
52
|
+
if (!shouldLog('warn'))
|
|
53
|
+
return;
|
|
54
|
+
if (context) {
|
|
55
|
+
console.warn(`[pmxt] ${message}`, context);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.warn(`[pmxt] ${message}`);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
error(message, context) {
|
|
62
|
+
if (!shouldLog('error'))
|
|
63
|
+
return;
|
|
64
|
+
if (context) {
|
|
65
|
+
console.error(`[pmxt] ${message}`, context);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
console.error(`[pmxt] ${message}`);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
setLevel(level) {
|
|
72
|
+
currentLevel = level;
|
|
73
|
+
},
|
|
74
|
+
getLevel() {
|
|
75
|
+
return currentLevel;
|
|
76
|
+
},
|
|
77
|
+
};
|
package/dist/pmxt/models.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface MarketOutcome {
|
|
|
22
22
|
/** 24-hour price change */
|
|
23
23
|
priceChange24h?: number;
|
|
24
24
|
/** Exchange-specific metadata */
|
|
25
|
-
metadata?: Record<string,
|
|
25
|
+
metadata?: Record<string, unknown>;
|
|
26
26
|
/** Best bid price from the order book (when includePrices=True) */
|
|
27
27
|
bestBid?: number;
|
|
28
28
|
/** Best ask price from the order book (when includePrices=True) */
|
|
@@ -201,7 +201,7 @@ export interface Trade {
|
|
|
201
201
|
side: "buy" | "sell" | "unknown";
|
|
202
202
|
}
|
|
203
203
|
/**
|
|
204
|
-
* An order (open, filled, or
|
|
204
|
+
* An order (open, filled, or canceled).
|
|
205
205
|
*/
|
|
206
206
|
export interface Order {
|
|
207
207
|
/** Order ID */
|
package/dist/pmxt/router.js
CHANGED
|
@@ -41,6 +41,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
42
|
exports.Router = void 0;
|
|
43
43
|
const client_js_1 = require("./client.js");
|
|
44
|
+
const logger_js_1 = require("./logger.js");
|
|
44
45
|
function convertMarket(raw) {
|
|
45
46
|
const outcomes = (raw.outcomes || []).map((o) => ({
|
|
46
47
|
outcomeId: o.outcomeId,
|
|
@@ -167,7 +168,7 @@ class Router extends client_js_1.Exchange {
|
|
|
167
168
|
}
|
|
168
169
|
}
|
|
169
170
|
async fetchMatches(marketOrParams = {}) {
|
|
170
|
-
|
|
171
|
+
logger_js_1.logger.warn('fetchMatches is deprecated, use fetchMarketMatches instead');
|
|
171
172
|
return this.fetchMarketMatches(marketOrParams);
|
|
172
173
|
}
|
|
173
174
|
async fetchEventMatches(eventOrParams = {}) {
|
|
@@ -224,6 +225,7 @@ class Router extends client_js_1.Exchange {
|
|
|
224
225
|
method: 'POST',
|
|
225
226
|
headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
|
|
226
227
|
body: JSON.stringify({ args: [query], credentials: this.getCredentials() }),
|
|
228
|
+
signal: AbortSignal.timeout(30_000),
|
|
227
229
|
});
|
|
228
230
|
if (!response.ok) {
|
|
229
231
|
const body = await response.json().catch(() => ({}));
|
|
@@ -121,7 +121,9 @@ class ServerManager {
|
|
|
121
121
|
try {
|
|
122
122
|
// Use native fetch to check health on the actual running port
|
|
123
123
|
// This avoids issues where this.api is configured with the wrong port
|
|
124
|
-
const response = await fetch(`http://localhost:${port}/health
|
|
124
|
+
const response = await fetch(`http://localhost:${port}/health`, {
|
|
125
|
+
signal: AbortSignal.timeout(5_000),
|
|
126
|
+
});
|
|
125
127
|
if (response.ok) {
|
|
126
128
|
const data = await response.json();
|
|
127
129
|
return data.status === "ok";
|
|
@@ -142,7 +144,9 @@ class ServerManager {
|
|
|
142
144
|
const info = this.getServerInfo();
|
|
143
145
|
if (info) {
|
|
144
146
|
try {
|
|
145
|
-
const response = await fetch(`http://localhost:${info.port}/health
|
|
147
|
+
const response = await fetch(`http://localhost:${info.port}/health`, {
|
|
148
|
+
signal: AbortSignal.timeout(5_000),
|
|
149
|
+
});
|
|
146
150
|
if (response.ok) {
|
|
147
151
|
const data = await response.json();
|
|
148
152
|
if (data.status === "ok")
|
package/dist/pmxt/ws-client.js
CHANGED
|
@@ -104,8 +104,21 @@ class SidecarWsClient {
|
|
|
104
104
|
const raw = typeof event.data === "string"
|
|
105
105
|
? event.data
|
|
106
106
|
: event.data.toString();
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
let msg;
|
|
108
|
+
try {
|
|
109
|
+
msg = JSON.parse(raw);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Non-JSON control frame -- ignore.
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
this.dispatch(msg);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
// Dispatch bug -- log and continue; don't kill the connection.
|
|
120
|
+
console.error('[SidecarWsClient] dispatch error:', err);
|
|
121
|
+
}
|
|
109
122
|
};
|
|
110
123
|
});
|
|
111
124
|
}
|
|
@@ -191,6 +204,9 @@ class SidecarWsClient {
|
|
|
191
204
|
if (credentials) {
|
|
192
205
|
message.credentials = credentials;
|
|
193
206
|
}
|
|
207
|
+
if (!this.ws) {
|
|
208
|
+
throw new errors_js_1.PmxtError('[ws-client] Cannot send: WebSocket not connected');
|
|
209
|
+
}
|
|
194
210
|
this.ws.send(JSON.stringify(message));
|
|
195
211
|
return this.waitForData(requestId, timeoutMs);
|
|
196
212
|
}
|
|
@@ -216,6 +232,9 @@ class SidecarWsClient {
|
|
|
216
232
|
if (credentials) {
|
|
217
233
|
message.credentials = credentials;
|
|
218
234
|
}
|
|
235
|
+
if (!this.ws) {
|
|
236
|
+
throw new errors_js_1.PmxtError('[ws-client] Cannot send: WebSocket not connected');
|
|
237
|
+
}
|
|
219
238
|
this.ws.send(JSON.stringify(message));
|
|
220
239
|
// Wait for first data event
|
|
221
240
|
await this.waitForData(requestId, timeoutMs);
|
package/generated/package.json
CHANGED
|
@@ -131,7 +131,7 @@ export const OrderStatusEnum = {
|
|
|
131
131
|
Pending: 'pending',
|
|
132
132
|
Open: 'open',
|
|
133
133
|
Filled: 'filled',
|
|
134
|
-
|
|
134
|
+
Canceled: 'canceled',
|
|
135
135
|
Rejected: 'rejected'
|
|
136
136
|
} as const;
|
|
137
137
|
export type OrderStatusEnum = typeof OrderStatusEnum[keyof typeof OrderStatusEnum];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmxtjs",
|
|
3
|
-
"version": "2.43.
|
|
3
|
+
"version": "2.43.24",
|
|
4
4
|
"description": "Unified prediction market data API - The ccxt for prediction markets",
|
|
5
5
|
"author": "PMXT Contributors",
|
|
6
6
|
"repository": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"unified"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"pmxt-core": "2.43.
|
|
46
|
+
"pmxt-core": "2.43.24",
|
|
47
47
|
"ws": "^8.18.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
package/pmxt/args.ts
CHANGED
package/pmxt/client.ts
CHANGED
|
@@ -392,7 +392,10 @@ export abstract class Exchange {
|
|
|
392
392
|
|
|
393
393
|
for (let attempt = 0; attempt <= delays.length; attempt++) {
|
|
394
394
|
try {
|
|
395
|
-
return await fetch(input,
|
|
395
|
+
return await fetch(input, {
|
|
396
|
+
...init,
|
|
397
|
+
signal: AbortSignal.timeout(30_000),
|
|
398
|
+
});
|
|
396
399
|
} catch (error) {
|
|
397
400
|
lastError = error;
|
|
398
401
|
if (attempt >= delays.length) break;
|
package/pmxt/errors.ts
CHANGED
|
@@ -49,29 +49,26 @@ export class PermissionDenied extends PmxtError {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
export class NotFoundError extends PmxtError {
|
|
52
|
-
constructor(message: string, exchange?: string) {
|
|
53
|
-
super(message,
|
|
52
|
+
constructor(message: string, exchange?: string, code: string = "NOT_FOUND") {
|
|
53
|
+
super(message, code, false, exchange);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
export class OrderNotFound extends NotFoundError {
|
|
58
58
|
constructor(orderId: string, exchange?: string) {
|
|
59
|
-
super(`Order not found: ${orderId}`, exchange);
|
|
60
|
-
(this as any).code = "ORDER_NOT_FOUND";
|
|
59
|
+
super(`Order not found: ${orderId}`, exchange, "ORDER_NOT_FOUND");
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
export class MarketNotFound extends NotFoundError {
|
|
65
64
|
constructor(marketId: string, exchange?: string) {
|
|
66
|
-
super(`Market not found: ${marketId}`, exchange);
|
|
67
|
-
(this as any).code = "MARKET_NOT_FOUND";
|
|
65
|
+
super(`Market not found: ${marketId}`, exchange, "MARKET_NOT_FOUND");
|
|
68
66
|
}
|
|
69
67
|
}
|
|
70
68
|
|
|
71
69
|
export class EventNotFound extends NotFoundError {
|
|
72
70
|
constructor(identifier: string, exchange?: string) {
|
|
73
|
-
super(`Event not found: ${identifier}`, exchange);
|
|
74
|
-
(this as any).code = "EVENT_NOT_FOUND";
|
|
71
|
+
super(`Event not found: ${identifier}`, exchange, "EVENT_NOT_FOUND");
|
|
75
72
|
}
|
|
76
73
|
}
|
|
77
74
|
|
|
@@ -137,23 +134,27 @@ const ERROR_CODE_MAP: Record<string, new (...args: any[]) => PmxtError> = {
|
|
|
137
134
|
};
|
|
138
135
|
|
|
139
136
|
/** Convert a server error response object into a typed PmxtError. */
|
|
140
|
-
export function fromServerError(errorData:
|
|
137
|
+
export function fromServerError(errorData: unknown): PmxtError {
|
|
141
138
|
if (typeof errorData === "string") {
|
|
142
139
|
return new PmxtError(errorData);
|
|
143
140
|
}
|
|
144
141
|
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
const
|
|
142
|
+
const data = errorData as Record<string, unknown>;
|
|
143
|
+
|
|
144
|
+
const message = (typeof data.message === "string" ? data.message : undefined) || "Unknown error";
|
|
145
|
+
const code = (typeof data.code === "string" ? data.code : undefined) || "UNKNOWN_ERROR";
|
|
146
|
+
const retryable = typeof data.retryable === "boolean" ? data.retryable : false;
|
|
147
|
+
const exchange = typeof data.exchange === "string" ? data.exchange : undefined;
|
|
149
148
|
|
|
150
149
|
const ErrorClass = ERROR_CODE_MAP[code];
|
|
151
150
|
|
|
152
151
|
if (ErrorClass === RateLimitExceeded) {
|
|
153
|
-
|
|
152
|
+
const retryAfter = typeof data.retryAfter === "number" ? data.retryAfter : undefined;
|
|
153
|
+
return new RateLimitExceeded(message, retryAfter, exchange);
|
|
154
154
|
}
|
|
155
155
|
if (ErrorClass === ValidationError) {
|
|
156
|
-
|
|
156
|
+
const field = typeof data.field === "string" ? data.field : undefined;
|
|
157
|
+
return new ValidationError(message, field, exchange);
|
|
157
158
|
}
|
|
158
159
|
if (ErrorClass) {
|
|
159
160
|
return new ErrorClass(message, exchange);
|
package/pmxt/feed-client.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { PmxtError } from "./errors.js";
|
|
|
11
11
|
|
|
12
12
|
export interface Ticker {
|
|
13
13
|
symbol: string;
|
|
14
|
-
info:
|
|
14
|
+
info: Record<string, unknown>;
|
|
15
15
|
timestamp: number | undefined;
|
|
16
16
|
datetime: string | undefined;
|
|
17
17
|
high: number | undefined;
|
|
@@ -44,7 +44,7 @@ export interface Market {
|
|
|
44
44
|
quote: string;
|
|
45
45
|
active: boolean;
|
|
46
46
|
type: string;
|
|
47
|
-
info:
|
|
47
|
+
info: Record<string, unknown>;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
export interface OracleRound {
|
|
@@ -94,7 +94,7 @@ export class FeedClient {
|
|
|
94
94
|
return this.get<Tickers>('fetchTickers', params);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
async fetchOHLCV(symbol: string, timeframe
|
|
97
|
+
async fetchOHLCV(symbol: string, timeframe: string = '1h', since?: number, limit?: number): Promise<OHLCV[]> {
|
|
98
98
|
return this.get<OHLCV[]>('fetchOHLCV', { symbol, timeframe, since, limit });
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -125,7 +125,10 @@ export class FeedClient {
|
|
|
125
125
|
|
|
126
126
|
const url = `${this.baseUrl}/api/feeds/${this.feedName}/${method}${qs ? '?' + qs : ''}`;
|
|
127
127
|
|
|
128
|
-
const response = await fetch(url, {
|
|
128
|
+
const response = await fetch(url, {
|
|
129
|
+
headers: this.headers,
|
|
130
|
+
signal: AbortSignal.timeout(30_000),
|
|
131
|
+
});
|
|
129
132
|
|
|
130
133
|
if (!response.ok) {
|
|
131
134
|
const body = await response.json().catch(() => ({}));
|
package/pmxt/logger.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logger for pmxt TypeScript SDK.
|
|
3
|
+
*
|
|
4
|
+
* Thin abstraction over console that:
|
|
5
|
+
* - Attaches a `[pmxt]` prefix for easy filtering
|
|
6
|
+
* - Supports log levels (debug, info, warn, error)
|
|
7
|
+
* - Respects a configurable level threshold via PMXT_LOG_LEVEL
|
|
8
|
+
* - Can be swapped for a real transport later
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
12
|
+
|
|
13
|
+
const LEVEL_PRIORITY: Record<LogLevel, number> = {
|
|
14
|
+
debug: 0,
|
|
15
|
+
info: 1,
|
|
16
|
+
warn: 2,
|
|
17
|
+
error: 3,
|
|
18
|
+
silent: 4,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function getDefaultLevel(): LogLevel {
|
|
22
|
+
if (typeof process !== 'undefined' && process.env?.PMXT_LOG_LEVEL) {
|
|
23
|
+
return process.env.PMXT_LOG_LEVEL as LogLevel;
|
|
24
|
+
}
|
|
25
|
+
return 'info';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let currentLevel: LogLevel = getDefaultLevel();
|
|
29
|
+
|
|
30
|
+
function shouldLog(level: LogLevel): boolean {
|
|
31
|
+
return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[currentLevel];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const logger = {
|
|
35
|
+
debug(message: string, context?: Record<string, unknown>): void {
|
|
36
|
+
if (!shouldLog('debug')) return;
|
|
37
|
+
if (context) {
|
|
38
|
+
console.debug(`[pmxt] ${message}`, context);
|
|
39
|
+
} else {
|
|
40
|
+
console.debug(`[pmxt] ${message}`);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
info(message: string, context?: Record<string, unknown>): void {
|
|
45
|
+
if (!shouldLog('info')) return;
|
|
46
|
+
if (context) {
|
|
47
|
+
console.info(`[pmxt] ${message}`, context);
|
|
48
|
+
} else {
|
|
49
|
+
console.info(`[pmxt] ${message}`);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
warn(message: string, context?: Record<string, unknown>): void {
|
|
54
|
+
if (!shouldLog('warn')) return;
|
|
55
|
+
if (context) {
|
|
56
|
+
console.warn(`[pmxt] ${message}`, context);
|
|
57
|
+
} else {
|
|
58
|
+
console.warn(`[pmxt] ${message}`);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
error(message: string, context?: Record<string, unknown>): void {
|
|
63
|
+
if (!shouldLog('error')) return;
|
|
64
|
+
if (context) {
|
|
65
|
+
console.error(`[pmxt] ${message}`, context);
|
|
66
|
+
} else {
|
|
67
|
+
console.error(`[pmxt] ${message}`);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
setLevel(level: LogLevel): void {
|
|
72
|
+
currentLevel = level;
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
getLevel(): LogLevel {
|
|
76
|
+
return currentLevel;
|
|
77
|
+
},
|
|
78
|
+
};
|
package/pmxt/models.ts
CHANGED
|
@@ -28,7 +28,7 @@ export interface MarketOutcome {
|
|
|
28
28
|
priceChange24h?: number;
|
|
29
29
|
|
|
30
30
|
/** Exchange-specific metadata */
|
|
31
|
-
metadata?: Record<string,
|
|
31
|
+
metadata?: Record<string, unknown>;
|
|
32
32
|
|
|
33
33
|
/** Best bid price from the order book (when includePrices=True) */
|
|
34
34
|
bestBid?: number;
|
|
@@ -271,7 +271,7 @@ export interface Trade {
|
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
/**
|
|
274
|
-
* An order (open, filled, or
|
|
274
|
+
* An order (open, filled, or canceled).
|
|
275
275
|
*/
|
|
276
276
|
export interface Order {
|
|
277
277
|
/** Order ID */
|
package/pmxt/router.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { Exchange, ExchangeOptions } from "./client.js";
|
|
9
|
+
import { logger } from "./logger.js";
|
|
9
10
|
import {
|
|
10
11
|
MatchResult,
|
|
11
12
|
MatchRelation,
|
|
@@ -204,7 +205,7 @@ export class Router extends Exchange {
|
|
|
204
205
|
limit?: number;
|
|
205
206
|
includePrices?: boolean;
|
|
206
207
|
} = {}): Promise<MatchResult[]> {
|
|
207
|
-
|
|
208
|
+
logger.warn('fetchMatches is deprecated, use fetchMarketMatches instead');
|
|
208
209
|
return this.fetchMarketMatches(marketOrParams as any);
|
|
209
210
|
}
|
|
210
211
|
|
|
@@ -297,6 +298,7 @@ export class Router extends Exchange {
|
|
|
297
298
|
method: 'POST',
|
|
298
299
|
headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
|
|
299
300
|
body: JSON.stringify({ args: [query], credentials: this.getCredentials() }),
|
|
301
|
+
signal: AbortSignal.timeout(30_000),
|
|
300
302
|
});
|
|
301
303
|
if (!response.ok) {
|
|
302
304
|
const body = await response.json().catch(() => ({}));
|
package/pmxt/server-manager.ts
CHANGED
|
@@ -108,7 +108,9 @@ export class ServerManager {
|
|
|
108
108
|
try {
|
|
109
109
|
// Use native fetch to check health on the actual running port
|
|
110
110
|
// This avoids issues where this.api is configured with the wrong port
|
|
111
|
-
const response = await fetch(`http://localhost:${port}/health
|
|
111
|
+
const response = await fetch(`http://localhost:${port}/health`, {
|
|
112
|
+
signal: AbortSignal.timeout(5_000),
|
|
113
|
+
});
|
|
112
114
|
if (response.ok) {
|
|
113
115
|
const data = await response.json();
|
|
114
116
|
return (data as any).status === "ok";
|
|
@@ -129,7 +131,9 @@ export class ServerManager {
|
|
|
129
131
|
const info = this.getServerInfo();
|
|
130
132
|
if (info) {
|
|
131
133
|
try {
|
|
132
|
-
const response = await fetch(`http://localhost:${info.port}/health
|
|
134
|
+
const response = await fetch(`http://localhost:${info.port}/health`, {
|
|
135
|
+
signal: AbortSignal.timeout(5_000),
|
|
136
|
+
});
|
|
133
137
|
if (response.ok) {
|
|
134
138
|
const data = await response.json() as any;
|
|
135
139
|
if (data.status === "ok") return;
|
package/pmxt/ws-client.ts
CHANGED
|
@@ -129,8 +129,19 @@ export class SidecarWsClient {
|
|
|
129
129
|
const raw = typeof event.data === "string"
|
|
130
130
|
? event.data
|
|
131
131
|
: event.data.toString();
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
let msg: WsMessage;
|
|
133
|
+
try {
|
|
134
|
+
msg = JSON.parse(raw);
|
|
135
|
+
} catch {
|
|
136
|
+
// Non-JSON control frame -- ignore.
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
this.dispatch(msg);
|
|
141
|
+
} catch (err) {
|
|
142
|
+
// Dispatch bug -- log and continue; don't kill the connection.
|
|
143
|
+
console.error('[SidecarWsClient] dispatch error:', err);
|
|
144
|
+
}
|
|
134
145
|
};
|
|
135
146
|
});
|
|
136
147
|
}
|
|
@@ -240,7 +251,10 @@ export class SidecarWsClient {
|
|
|
240
251
|
message.credentials = credentials;
|
|
241
252
|
}
|
|
242
253
|
|
|
243
|
-
this.ws
|
|
254
|
+
if (!this.ws) {
|
|
255
|
+
throw new PmxtError('[ws-client] Cannot send: WebSocket not connected');
|
|
256
|
+
}
|
|
257
|
+
this.ws.send(JSON.stringify(message));
|
|
244
258
|
|
|
245
259
|
return this.waitForData(requestId, timeoutMs);
|
|
246
260
|
}
|
|
@@ -278,7 +292,10 @@ export class SidecarWsClient {
|
|
|
278
292
|
message.credentials = credentials;
|
|
279
293
|
}
|
|
280
294
|
|
|
281
|
-
this.ws
|
|
295
|
+
if (!this.ws) {
|
|
296
|
+
throw new PmxtError('[ws-client] Cannot send: WebSocket not connected');
|
|
297
|
+
}
|
|
298
|
+
this.ws.send(JSON.stringify(message));
|
|
282
299
|
|
|
283
300
|
// Wait for first data event
|
|
284
301
|
await this.waitForData(requestId, timeoutMs);
|