pmxt-core 1.1.2 → 1.1.4

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.
@@ -24,12 +24,27 @@ async function fetchOHLCV(id, params) {
24
24
  const now = Math.floor(Date.now() / 1000);
25
25
  let startTs = now - (24 * 60 * 60);
26
26
  let endTs = now;
27
- if (params.start) {
28
- startTs = Math.floor(params.start.getTime() / 1000);
27
+ // Helper to handle string dates (from JSON)
28
+ // IMPORTANT: Python sends naive datetimes as ISO strings without 'Z' suffix.
29
+ // We must treat these as UTC, not local time.
30
+ const ensureDate = (d) => {
31
+ if (typeof d === 'string') {
32
+ // If string doesn't end with 'Z' and doesn't have timezone offset, append 'Z'
33
+ if (!d.endsWith('Z') && !d.match(/[+-]\d{2}:\d{2}$/)) {
34
+ return new Date(d + 'Z');
35
+ }
36
+ return new Date(d);
37
+ }
38
+ return d;
39
+ };
40
+ const pStart = params.start ? ensureDate(params.start) : undefined;
41
+ const pEnd = params.end ? ensureDate(params.end) : undefined;
42
+ if (pStart) {
43
+ startTs = Math.floor(pStart.getTime() / 1000);
29
44
  }
30
- if (params.end) {
31
- endTs = Math.floor(params.end.getTime() / 1000);
32
- if (!params.start) {
45
+ if (pEnd) {
46
+ endTs = Math.floor(pEnd.getTime() / 1000);
47
+ if (!pStart) {
33
48
  startTs = endTs - (24 * 60 * 60);
34
49
  }
35
50
  }
@@ -20,9 +20,24 @@ async function fetchOHLCV(id, params) {
20
20
  const nowTs = Math.floor(Date.now() / 1000);
21
21
  // 1. Smart Lookback Calculation
22
22
  // If start/end not provided, calculate window based on limit * resolution
23
- let startTs = params.start ? Math.floor(params.start.getTime() / 1000) : 0;
24
- let endTs = params.end ? Math.floor(params.end.getTime() / 1000) : nowTs;
25
- if (!params.start) {
23
+ // Helper to handle string dates (from JSON)
24
+ // IMPORTANT: Python sends naive datetimes as ISO strings without 'Z' suffix.
25
+ // We must treat these as UTC, not local time.
26
+ const ensureDate = (d) => {
27
+ if (typeof d === 'string') {
28
+ // If string doesn't end with 'Z' and doesn't have timezone offset, append 'Z'
29
+ if (!d.endsWith('Z') && !d.match(/[+-]\d{2}:\d{2}$/)) {
30
+ return new Date(d + 'Z');
31
+ }
32
+ return new Date(d);
33
+ }
34
+ return d;
35
+ };
36
+ const pStart = params.start ? ensureDate(params.start) : undefined;
37
+ const pEnd = params.end ? ensureDate(params.end) : undefined;
38
+ let startTs = pStart ? Math.floor(pStart.getTime() / 1000) : 0;
39
+ let endTs = pEnd ? Math.floor(pEnd.getTime() / 1000) : nowTs;
40
+ if (!pStart) {
26
41
  // Default limit is usually 20 in the example, but safety margin is good.
27
42
  // If limit is not set, we default to 100 candles.
28
43
  const count = params.limit || 100;
@@ -44,18 +59,35 @@ async function fetchOHLCV(id, params) {
44
59
  // Polymarket returns random tick timestamps (e.g. 1:00:21).
45
60
  // We want to normalize this to the start of the bucket (1:00:00).
46
61
  const resolutionMs = fidelity * 60 * 1000;
47
- const candles = history.map((item) => {
62
+ // 2. Client-side Aggregation
63
+ // Polymarket returns tick data. We must group by time bucket to create true candles.
64
+ const buckets = new Map();
65
+ history.forEach((item) => {
48
66
  const rawMs = item.t * 1000;
49
67
  const snappedMs = Math.floor(rawMs / resolutionMs) * resolutionMs;
50
- return {
51
- timestamp: snappedMs, // Aligned timestamp
52
- open: item.p,
53
- high: item.p,
54
- low: item.p,
55
- close: item.p,
56
- volume: undefined
57
- };
68
+ const price = Number(item.p);
69
+ const volume = Number(item.s || item.v || 0); // specific field depends on api, usually 's' for size
70
+ if (!buckets.has(snappedMs)) {
71
+ buckets.set(snappedMs, {
72
+ timestamp: snappedMs,
73
+ open: price,
74
+ high: price,
75
+ low: price,
76
+ close: price,
77
+ volume: volume
78
+ });
79
+ }
80
+ else {
81
+ const candle = buckets.get(snappedMs);
82
+ candle.high = Math.max(candle.high, price);
83
+ candle.low = Math.min(candle.low, price);
84
+ candle.close = price; // Assuming history is sorted by time. If not, we need to track timestamps.
85
+ candle.volume = (candle.volume || 0) + volume;
86
+ // If history is not guaranteed sorted, we should track first/last timestamps per bucket.
87
+ // But usually /prices-history is sorted. We'll assume sorted for efficiency.
88
+ }
58
89
  });
90
+ const candles = Array.from(buckets.values()).sort((a, b) => a.timestamp - b.timestamp);
59
91
  // Apply limit if specified
60
92
  if (params.limit && candles.length > params.limit) {
61
93
  return candles.slice(-params.limit);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmxt-core",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "pmxt is a unified prediction market data API. The ccxt for prediction markets.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -29,8 +29,8 @@
29
29
  "test": "jest -c jest.config.js",
30
30
  "server": "tsx watch src/server/index.ts",
31
31
  "server:prod": "node dist/server/index.js",
32
- "generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=1.1.2,library=urllib3",
33
- "generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=1.1.2,supportsES6=true,typescriptThreePlus=true",
32
+ "generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=1.1.4,library=urllib3",
33
+ "generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=1.1.4,supportsES6=true,typescriptThreePlus=true",
34
34
  "generate:docs": "node ../scripts/generate-api-docs.js",
35
35
  "generate:sdk:all": "npm run generate:sdk:python && npm run generate:sdk:typescript && npm run generate:docs"
36
36
  },