pmxt-core 2.41.7 → 2.42.2

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.
Files changed (47) hide show
  1. package/dist/exchanges/kalshi/api.d.ts +1 -1
  2. package/dist/exchanges/kalshi/api.js +1 -1
  3. package/dist/exchanges/limitless/api.d.ts +1 -1
  4. package/dist/exchanges/limitless/api.js +1 -1
  5. package/dist/exchanges/myriad/api.d.ts +1 -1
  6. package/dist/exchanges/myriad/api.js +1 -1
  7. package/dist/exchanges/opinion/api.d.ts +1 -1
  8. package/dist/exchanges/opinion/api.js +1 -1
  9. package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
  10. package/dist/exchanges/polymarket/api-clob.js +1 -1
  11. package/dist/exchanges/polymarket/api-data.d.ts +1 -1
  12. package/dist/exchanges/polymarket/api-data.js +1 -1
  13. package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
  14. package/dist/exchanges/polymarket/api-gamma.js +1 -1
  15. package/dist/exchanges/probable/api.d.ts +1 -1
  16. package/dist/exchanges/probable/api.js +1 -1
  17. package/dist/feeds/base-feed.d.ts +31 -0
  18. package/dist/feeds/base-feed.js +76 -0
  19. package/dist/feeds/binance/binance-feed.d.ts +29 -0
  20. package/dist/feeds/binance/binance-feed.js +189 -0
  21. package/dist/feeds/binance/index.d.ts +4 -0
  22. package/dist/feeds/binance/index.js +10 -0
  23. package/dist/feeds/binance/normalizer.d.ts +7 -0
  24. package/dist/feeds/binance/normalizer.js +51 -0
  25. package/dist/feeds/binance/types.d.ts +32 -0
  26. package/dist/feeds/binance/types.js +11 -0
  27. package/dist/feeds/chainlink/chainlink-feed.d.ts +38 -0
  28. package/dist/feeds/chainlink/chainlink-feed.js +241 -0
  29. package/dist/feeds/chainlink/index.d.ts +4 -0
  30. package/dist/feeds/chainlink/index.js +17 -0
  31. package/dist/feeds/chainlink/normalizer.d.ts +9 -0
  32. package/dist/feeds/chainlink/normalizer.js +99 -0
  33. package/dist/feeds/chainlink/types.d.ts +75 -0
  34. package/dist/feeds/chainlink/types.js +51 -0
  35. package/dist/feeds/index.d.ts +6 -0
  36. package/dist/feeds/index.js +21 -0
  37. package/dist/feeds/interfaces.d.ts +23 -0
  38. package/dist/feeds/interfaces.js +2 -0
  39. package/dist/feeds/types.d.ts +123 -0
  40. package/dist/feeds/types.js +7 -0
  41. package/dist/index.d.ts +1 -0
  42. package/dist/index.js +1 -0
  43. package/dist/server/feed-factory.d.ts +6 -0
  44. package/dist/server/feed-factory.js +34 -0
  45. package/dist/server/feed-routes.d.ts +6 -0
  46. package/dist/server/feed-routes.js +166 -0
  47. package/package.json +3 -3
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ChainlinkFeed = void 0;
7
+ const ws_1 = __importDefault(require("ws"));
8
+ const axios_1 = __importDefault(require("axios"));
9
+ const base_feed_1 = require("../base-feed");
10
+ const types_1 = require("./types");
11
+ const normalizer_1 = require("./normalizer");
12
+ class ChainlinkFeed extends base_feed_1.BaseDataFeed {
13
+ name = 'chainlink';
14
+ description = 'Chainlink price feeds (ETH, BTC, XRP, SOL) on Polygon via pmxt-ohlc';
15
+ client;
16
+ wsUrl;
17
+ wsApiKey;
18
+ reconnectIntervalMs;
19
+ ws = null;
20
+ subscriptions = [];
21
+ latestTickers = new Map();
22
+ isTerminated = false;
23
+ reconnectTimer = null;
24
+ connectionPromise = null;
25
+ constructor(config, options) {
26
+ super(options);
27
+ const baseURL = config.baseUrl ?? types_1.CHAINLINK_DEFAULTS.baseUrl;
28
+ this.client = axios_1.default.create({
29
+ baseURL,
30
+ headers: { 'X-API-Key': config.apiKey },
31
+ timeout: 10_000,
32
+ });
33
+ this.wsUrl = config.wsUrl ?? types_1.CHAINLINK_DEFAULTS.wsUrl;
34
+ this.wsApiKey = config.wsApiKey ?? config.apiKey;
35
+ this.reconnectIntervalMs = config.reconnectIntervalMs ?? types_1.CHAINLINK_DEFAULTS.reconnectIntervalMs;
36
+ }
37
+ // -- Lifecycle --
38
+ async connect() {
39
+ if (this.ws)
40
+ return;
41
+ if (this.connectionPromise)
42
+ return this.connectionPromise;
43
+ this.isTerminated = false;
44
+ this.connectionPromise = this.establishConnection();
45
+ return this.connectionPromise;
46
+ }
47
+ async close() {
48
+ this.isTerminated = true;
49
+ if (this.reconnectTimer) {
50
+ clearTimeout(this.reconnectTimer);
51
+ this.reconnectTimer = null;
52
+ }
53
+ if (this.ws) {
54
+ this.ws.close(1000, 'client_close');
55
+ this.ws = null;
56
+ }
57
+ this.connectionPromise = null;
58
+ this.subscriptions = [];
59
+ }
60
+ // -- CCXT: loadMarkets --
61
+ async loadMarkets() {
62
+ const markets = {};
63
+ for (const t of types_1.SUPPORTED_TOKENS) {
64
+ markets[t.pair] = {
65
+ id: t.short,
66
+ symbol: t.pair,
67
+ base: t.base,
68
+ quote: t.quote,
69
+ active: true,
70
+ type: 'spot',
71
+ spot: true,
72
+ margin: false,
73
+ swap: false,
74
+ future: false,
75
+ option: false,
76
+ contract: false,
77
+ precision: { amount: undefined, price: t.decimals },
78
+ limits: {},
79
+ info: { proxyAddress: t.proxyAddress, decimals: t.decimals },
80
+ };
81
+ }
82
+ return markets;
83
+ }
84
+ // -- CCXT: fetchTicker --
85
+ async fetchTickerImpl(symbol) {
86
+ const cached = this.latestTickers.get(symbol.toUpperCase());
87
+ if (cached)
88
+ return cached;
89
+ const token = types_1.TOKEN_BY_PAIR.get(symbol.toUpperCase());
90
+ if (!token) {
91
+ throw new Error(`Unsupported Chainlink symbol: ${symbol}. Supported: ${types_1.SUPPORTED_TOKENS.map((t) => t.pair).join(', ')}`);
92
+ }
93
+ const { data } = await this.client.get('/v1/chainlink/latest-prices');
94
+ const now = Date.now();
95
+ const record = data.data.find((r) => r.token.toLowerCase() === token.short);
96
+ if (!record) {
97
+ throw new Error(`No price data returned for ${symbol}`);
98
+ }
99
+ return (0, normalizer_1.normalizeLatestToTicker)(record, now);
100
+ }
101
+ // -- CCXT: fetchTickers --
102
+ async fetchTickersImpl(symbols) {
103
+ const { data } = await this.client.get('/v1/chainlink/latest-prices');
104
+ const now = Date.now();
105
+ const requested = symbols
106
+ ? new Set(symbols.map((s) => s.toUpperCase()))
107
+ : undefined;
108
+ const result = {};
109
+ for (const record of data.data) {
110
+ const token = types_1.SUPPORTED_TOKENS.find((t) => t.short === record.token.toLowerCase());
111
+ if (!token)
112
+ continue;
113
+ if (requested && !requested.has(token.pair))
114
+ continue;
115
+ if (record.price === null || record.price === undefined)
116
+ continue;
117
+ const ticker = (0, normalizer_1.normalizeLatestToTicker)(record, now);
118
+ result[ticker.symbol] = ticker;
119
+ }
120
+ return result;
121
+ }
122
+ // -- CCXT: watchTicker --
123
+ watchTickerImpl(symbol, callback) {
124
+ const sub = { symbol: symbol.toUpperCase(), callback };
125
+ this.subscriptions = [...this.subscriptions, sub];
126
+ this.ensureConnected();
127
+ return () => {
128
+ this.subscriptions = this.subscriptions.filter((s) => s !== sub);
129
+ };
130
+ }
131
+ // -- CCXT: fetchOHLCV (not supported) --
132
+ async fetchOHLCVImpl(_symbol, _timeframe, _since, _limit) {
133
+ throw new Error('Chainlink feed does not provide OHLCV candles. ' +
134
+ 'Use fetchOracleHistory() for raw AnswerUpdated records.');
135
+ }
136
+ // -- CCXT: fetchOrderBook (not applicable) --
137
+ async fetchOrderBookImpl(_symbol, _limit) {
138
+ throw new Error('Chainlink oracle feeds do not have order books.');
139
+ }
140
+ // -- pmxt extensions: Oracle --
141
+ async fetchOracleRound(params) {
142
+ const token = types_1.TOKEN_BY_PAIR.get(params.feed.toUpperCase());
143
+ if (!token) {
144
+ throw new Error(`Unsupported Chainlink feed: ${params.feed}. Supported: ${types_1.SUPPORTED_TOKENS.map((t) => t.pair).join(', ')}`);
145
+ }
146
+ const { data } = await this.client.get('/v1/chainlink/prices', { params: { token: token.short, max_size: 1, order: 'desc' } });
147
+ if (data.data.length === 0) {
148
+ throw new Error(`No oracle data returned for ${params.feed}`);
149
+ }
150
+ return (0, normalizer_1.normalizePriceRecordToOracleRound)(data.data[0]);
151
+ }
152
+ async fetchOracleHistory(params) {
153
+ const token = types_1.TOKEN_BY_PAIR.get(params.feed.toUpperCase());
154
+ if (!token) {
155
+ throw new Error(`Unsupported Chainlink feed: ${params.feed}. Supported: ${types_1.SUPPORTED_TOKENS.map((t) => t.pair).join(', ')}`);
156
+ }
157
+ const { data } = await this.client.get('/v1/chainlink/prices', { params: { token: token.short, max_size: params.limit ?? 500, order: 'desc' } });
158
+ return data.data.map(normalizer_1.normalizePriceRecordToOracleRound);
159
+ }
160
+ async fetchHistoricalPrices(symbol, opts) {
161
+ const token = types_1.TOKEN_BY_PAIR.get(symbol.toUpperCase());
162
+ if (!token) {
163
+ throw new Error(`Unsupported Chainlink symbol: ${symbol}. Supported: ${types_1.SUPPORTED_TOKENS.map((t) => t.pair).join(', ')}`);
164
+ }
165
+ const queryParams = { token: token.short };
166
+ if (opts?.fromTimestamp !== undefined)
167
+ queryParams.from_timestamp = opts.fromTimestamp;
168
+ if (opts?.untilTimestamp !== undefined)
169
+ queryParams.until_timestamp = opts.untilTimestamp;
170
+ if (opts?.maxSize !== undefined)
171
+ queryParams.max_size = opts.maxSize;
172
+ if (opts?.order !== undefined)
173
+ queryParams.order = opts.order;
174
+ const { data } = await this.client.get('/v1/chainlink/prices', { params: queryParams });
175
+ return data.data.map(normalizer_1.normalizePriceRecordToTicker);
176
+ }
177
+ // -- Internal WebSocket --
178
+ async ensureConnected() {
179
+ if (this.ws && this.ws.readyState === ws_1.default.OPEN)
180
+ return;
181
+ await this.connect();
182
+ }
183
+ establishConnection() {
184
+ return new Promise((resolve, reject) => {
185
+ const url = `${this.wsUrl}?key=${this.wsApiKey}`;
186
+ const ws = new ws_1.default(url);
187
+ ws.on('open', () => {
188
+ this.ws = ws;
189
+ this.connectionPromise = null;
190
+ ws.send(JSON.stringify({ op: 'subscribe_all' }));
191
+ resolve();
192
+ });
193
+ ws.on('message', (data) => {
194
+ this.handleMessage(data);
195
+ });
196
+ ws.on('close', () => {
197
+ this.ws = null;
198
+ this.connectionPromise = null;
199
+ if (!this.isTerminated)
200
+ this.scheduleReconnect();
201
+ });
202
+ ws.on('error', (err) => {
203
+ this.ws = null;
204
+ this.connectionPromise = null;
205
+ if (!this.isTerminated)
206
+ this.scheduleReconnect();
207
+ reject(err);
208
+ });
209
+ });
210
+ }
211
+ handleMessage(data) {
212
+ const text = typeof data === 'string' ? data : data.toString();
213
+ let msg;
214
+ try {
215
+ msg = JSON.parse(text);
216
+ }
217
+ catch {
218
+ return;
219
+ }
220
+ if (msg.op !== 'event')
221
+ return;
222
+ const event = msg;
223
+ const ticker = (0, normalizer_1.normalizeWsEventToTicker)(event);
224
+ this.latestTickers = new Map(this.latestTickers).set(ticker.symbol, ticker);
225
+ for (const sub of this.subscriptions) {
226
+ if (sub.symbol === ticker.symbol) {
227
+ sub.callback(ticker);
228
+ }
229
+ }
230
+ }
231
+ scheduleReconnect() {
232
+ if (this.reconnectTimer)
233
+ return;
234
+ this.reconnectTimer = setTimeout(() => {
235
+ this.reconnectTimer = null;
236
+ if (!this.isTerminated)
237
+ this.connect();
238
+ }, this.reconnectIntervalMs);
239
+ }
240
+ }
241
+ exports.ChainlinkFeed = ChainlinkFeed;
@@ -0,0 +1,4 @@
1
+ export { ChainlinkFeed } from './chainlink-feed';
2
+ export { chainlinkNormalizer, normalizeLatestToTicker, normalizePriceRecordToTicker, normalizePriceRecordToOracleRound, normalizeWsEventToTicker, normalizeWsEventToOracleRound, } from './normalizer';
3
+ export type { ChainlinkFeedConfig, ChainlinkLatestPriceRecord, ChainlinkPriceRecord, ChainlinkWsEvent, ChainlinkWsMessage, } from './types';
4
+ export { CHAINLINK_DEFAULTS, SUPPORTED_TOKENS, TOKEN_BY_SHORT, TOKEN_BY_PAIR } from './types';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TOKEN_BY_PAIR = exports.TOKEN_BY_SHORT = exports.SUPPORTED_TOKENS = exports.CHAINLINK_DEFAULTS = exports.normalizeWsEventToOracleRound = exports.normalizeWsEventToTicker = exports.normalizePriceRecordToOracleRound = exports.normalizePriceRecordToTicker = exports.normalizeLatestToTicker = exports.chainlinkNormalizer = exports.ChainlinkFeed = void 0;
4
+ var chainlink_feed_1 = require("./chainlink-feed");
5
+ Object.defineProperty(exports, "ChainlinkFeed", { enumerable: true, get: function () { return chainlink_feed_1.ChainlinkFeed; } });
6
+ var normalizer_1 = require("./normalizer");
7
+ Object.defineProperty(exports, "chainlinkNormalizer", { enumerable: true, get: function () { return normalizer_1.chainlinkNormalizer; } });
8
+ Object.defineProperty(exports, "normalizeLatestToTicker", { enumerable: true, get: function () { return normalizer_1.normalizeLatestToTicker; } });
9
+ Object.defineProperty(exports, "normalizePriceRecordToTicker", { enumerable: true, get: function () { return normalizer_1.normalizePriceRecordToTicker; } });
10
+ Object.defineProperty(exports, "normalizePriceRecordToOracleRound", { enumerable: true, get: function () { return normalizer_1.normalizePriceRecordToOracleRound; } });
11
+ Object.defineProperty(exports, "normalizeWsEventToTicker", { enumerable: true, get: function () { return normalizer_1.normalizeWsEventToTicker; } });
12
+ Object.defineProperty(exports, "normalizeWsEventToOracleRound", { enumerable: true, get: function () { return normalizer_1.normalizeWsEventToOracleRound; } });
13
+ var types_1 = require("./types");
14
+ Object.defineProperty(exports, "CHAINLINK_DEFAULTS", { enumerable: true, get: function () { return types_1.CHAINLINK_DEFAULTS; } });
15
+ Object.defineProperty(exports, "SUPPORTED_TOKENS", { enumerable: true, get: function () { return types_1.SUPPORTED_TOKENS; } });
16
+ Object.defineProperty(exports, "TOKEN_BY_SHORT", { enumerable: true, get: function () { return types_1.TOKEN_BY_SHORT; } });
17
+ Object.defineProperty(exports, "TOKEN_BY_PAIR", { enumerable: true, get: function () { return types_1.TOKEN_BY_PAIR; } });
@@ -0,0 +1,9 @@
1
+ import { Ticker, OracleRound } from '../types';
2
+ import { IFeedNormalizer } from '../interfaces';
3
+ import { ChainlinkLatestPriceRecord, ChainlinkPriceRecord, ChainlinkWsEvent } from './types';
4
+ export declare const chainlinkNormalizer: IFeedNormalizer<ChainlinkLatestPriceRecord, ChainlinkPriceRecord>;
5
+ export declare function normalizeLatestToTicker(raw: ChainlinkLatestPriceRecord, now: number): Ticker;
6
+ export declare function normalizePriceRecordToTicker(raw: ChainlinkPriceRecord): Ticker;
7
+ export declare function normalizePriceRecordToOracleRound(raw: ChainlinkPriceRecord): OracleRound;
8
+ export declare function normalizeWsEventToTicker(event: ChainlinkWsEvent): Ticker;
9
+ export declare function normalizeWsEventToOracleRound(event: ChainlinkWsEvent): OracleRound;
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.chainlinkNormalizer = void 0;
4
+ exports.normalizeLatestToTicker = normalizeLatestToTicker;
5
+ exports.normalizePriceRecordToTicker = normalizePriceRecordToTicker;
6
+ exports.normalizePriceRecordToOracleRound = normalizePriceRecordToOracleRound;
7
+ exports.normalizeWsEventToTicker = normalizeWsEventToTicker;
8
+ exports.normalizeWsEventToOracleRound = normalizeWsEventToOracleRound;
9
+ const types_1 = require("./types");
10
+ // ----------------------------------------------------------------------------
11
+ // Chainlink normalizer — produces CCXT-compatible Ticker and OracleRound.
12
+ // ----------------------------------------------------------------------------
13
+ function makeTicker(symbol, price, timestamp, info) {
14
+ return {
15
+ symbol,
16
+ info,
17
+ timestamp,
18
+ datetime: new Date(timestamp).toISOString(),
19
+ high: undefined,
20
+ low: undefined,
21
+ bid: undefined,
22
+ bidVolume: undefined,
23
+ ask: undefined,
24
+ askVolume: undefined,
25
+ vwap: undefined,
26
+ open: undefined,
27
+ close: undefined,
28
+ last: price,
29
+ previousClose: undefined,
30
+ change: undefined,
31
+ percentage: undefined,
32
+ average: undefined,
33
+ quoteVolume: undefined,
34
+ baseVolume: undefined,
35
+ indexPrice: undefined,
36
+ markPrice: undefined,
37
+ };
38
+ }
39
+ exports.chainlinkNormalizer = {
40
+ normalizeTicker(raw) {
41
+ if (raw.price === null || raw.price === undefined) {
42
+ throw new Error(`Chainlink returned null price for token=${raw.token}`);
43
+ }
44
+ const token = types_1.TOKEN_BY_SHORT.get(raw.token.toLowerCase());
45
+ return makeTicker(token?.pair ?? `${raw.token.toUpperCase()}/USD`, raw.price, Date.now(), raw);
46
+ },
47
+ };
48
+ function normalizeLatestToTicker(raw, now) {
49
+ if (raw.price === null || raw.price === undefined) {
50
+ throw new Error(`Chainlink returned null price for token=${raw.token}`);
51
+ }
52
+ const token = types_1.TOKEN_BY_SHORT.get(raw.token.toLowerCase());
53
+ return makeTicker(token?.pair ?? `${raw.token.toUpperCase()}/USD`, raw.price, now, raw);
54
+ }
55
+ function normalizePriceRecordToTicker(raw) {
56
+ if (raw.price === null || raw.price === undefined) {
57
+ throw new Error(`Chainlink returned null price for token=${raw.token} at timestamp=${raw.timestamp}`);
58
+ }
59
+ const token = types_1.TOKEN_BY_SHORT.get(raw.token.toLowerCase());
60
+ return makeTicker(token?.pair ?? `${raw.token.toUpperCase()}/USD`, raw.price, raw.timestamp * 1000, raw);
61
+ }
62
+ function normalizePriceRecordToOracleRound(raw) {
63
+ if (raw.price === null || raw.price === undefined) {
64
+ throw new Error(`Chainlink returned null price for token=${raw.token} at timestamp=${raw.timestamp}`);
65
+ }
66
+ const token = types_1.TOKEN_BY_SHORT.get(raw.token.toLowerCase());
67
+ const decimals = token?.decimals ?? 8;
68
+ return {
69
+ feed: token?.pair ?? `${raw.token.toUpperCase()}/USD`,
70
+ roundId: String(raw.timestamp),
71
+ answer: raw.price,
72
+ startedAt: raw.timestamp,
73
+ updatedAt: raw.timestamp,
74
+ answeredInRound: String(raw.timestamp),
75
+ decimals,
76
+ description: token
77
+ ? `${token.base} / ${token.quote} on Polygon`
78
+ : undefined,
79
+ };
80
+ }
81
+ function normalizeWsEventToTicker(event) {
82
+ return makeTicker(event.symbol, event.price, event.updated_at * 1000, event);
83
+ }
84
+ function normalizeWsEventToOracleRound(event) {
85
+ const token = types_1.TOKEN_BY_PAIR.get(event.symbol);
86
+ const decimals = token?.decimals ?? 8;
87
+ return {
88
+ feed: event.symbol,
89
+ roundId: String(event.round_id),
90
+ answer: event.price,
91
+ startedAt: event.updated_at,
92
+ updatedAt: event.updated_at,
93
+ answeredInRound: String(event.round_id),
94
+ decimals,
95
+ description: token
96
+ ? `${token.base} / ${token.quote} on Polygon`
97
+ : undefined,
98
+ };
99
+ }
@@ -0,0 +1,75 @@
1
+ export interface ChainlinkLatestPriceRecord {
2
+ readonly token: string;
3
+ readonly price: number | null;
4
+ }
5
+ export interface ChainlinkLatestPricesResponse {
6
+ readonly data: readonly ChainlinkLatestPriceRecord[];
7
+ }
8
+ export interface ChainlinkPriceRecord {
9
+ readonly timestamp: number;
10
+ readonly date: string;
11
+ readonly token: string;
12
+ readonly price: number | null;
13
+ }
14
+ export interface ChainlinkPricesResponse {
15
+ readonly data: readonly ChainlinkPriceRecord[];
16
+ }
17
+ export interface ChainlinkFeedConfig {
18
+ /** Base URL for the Chainlink REST API. */
19
+ readonly baseUrl?: string;
20
+ /** API key for REST authentication (X-API-Key header). */
21
+ readonly apiKey: string;
22
+ /** WebSocket URL for live Chainlink events. */
23
+ readonly wsUrl?: string;
24
+ /** API key for WebSocket authentication (may differ from REST key). */
25
+ readonly wsApiKey?: string;
26
+ /** Reconnect interval in ms (default: 5000). */
27
+ readonly reconnectIntervalMs?: number;
28
+ }
29
+ export declare const CHAINLINK_DEFAULTS: {
30
+ readonly baseUrl: string;
31
+ readonly wsUrl: string;
32
+ readonly reconnectIntervalMs: 5000;
33
+ };
34
+ export interface ChainlinkToken {
35
+ readonly short: string;
36
+ readonly pair: string;
37
+ readonly base: string;
38
+ readonly quote: string;
39
+ readonly proxyAddress: string;
40
+ readonly decimals: number;
41
+ }
42
+ export declare const SUPPORTED_TOKENS: readonly ChainlinkToken[];
43
+ /** Map short token name -> token metadata. */
44
+ export declare const TOKEN_BY_SHORT: Map<string, ChainlinkToken>;
45
+ /** Map pair string (e.g. "ETH/USD") -> token metadata. */
46
+ export declare const TOKEN_BY_PAIR: Map<string, ChainlinkToken>;
47
+ export interface ChainlinkWsEvent {
48
+ readonly op: 'event';
49
+ readonly source: 'chainlink';
50
+ readonly chain: string;
51
+ readonly symbol: string;
52
+ readonly aggregator: string;
53
+ readonly round_id: number;
54
+ readonly price: number;
55
+ readonly updated_at: number;
56
+ readonly block_number: number;
57
+ readonly log_index: number;
58
+ readonly tx_hash: string;
59
+ }
60
+ export interface ChainlinkWsAck {
61
+ readonly op: 'ack';
62
+ readonly subscribed_all?: boolean;
63
+ readonly subscribed?: readonly string[];
64
+ readonly unsubscribed_all?: boolean;
65
+ readonly unsubscribed?: readonly string[];
66
+ }
67
+ export interface ChainlinkWsError {
68
+ readonly op: 'error';
69
+ readonly code: string;
70
+ readonly reason: string;
71
+ }
72
+ export interface ChainlinkWsPong {
73
+ readonly op: 'pong';
74
+ }
75
+ export type ChainlinkWsMessage = ChainlinkWsEvent | ChainlinkWsAck | ChainlinkWsError | ChainlinkWsPong;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ // ----------------------------------------------------------------------------
3
+ // Chainlink Price Feed — raw API types and configuration
4
+ // REST: https://github.com/pmxt-dev/pmxt-ohlc/blob/main/docs/CHAINLINK_API.md
5
+ // WS: https://github.com/pmxt-dev/pmxt-ohlc/blob/main/docs/CHAINLINK_WS.md
6
+ // ----------------------------------------------------------------------------
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.TOKEN_BY_PAIR = exports.TOKEN_BY_SHORT = exports.SUPPORTED_TOKENS = exports.CHAINLINK_DEFAULTS = void 0;
9
+ exports.CHAINLINK_DEFAULTS = {
10
+ baseUrl: process.env.CHAINLINK_API_URL || '',
11
+ wsUrl: process.env.CHAINLINK_WS_URL || '',
12
+ reconnectIntervalMs: 5000,
13
+ };
14
+ exports.SUPPORTED_TOKENS = [
15
+ {
16
+ short: 'eth',
17
+ pair: 'ETH/USD',
18
+ base: 'ETH',
19
+ quote: 'USD',
20
+ proxyAddress: '0xF9680D99D6C9589e2a93a78A04A279e509205945',
21
+ decimals: 8,
22
+ },
23
+ {
24
+ short: 'btc',
25
+ pair: 'BTC/USD',
26
+ base: 'BTC',
27
+ quote: 'USD',
28
+ proxyAddress: '0xc907E116054Ad103354f2D350FD2514433D57F6f',
29
+ decimals: 8,
30
+ },
31
+ {
32
+ short: 'xrp',
33
+ pair: 'XRP/USD',
34
+ base: 'XRP',
35
+ quote: 'USD',
36
+ proxyAddress: '0x785ba89291f676b5386652eB12b30cF361020694',
37
+ decimals: 8,
38
+ },
39
+ {
40
+ short: 'sol',
41
+ pair: 'SOL/USD',
42
+ base: 'SOL',
43
+ quote: 'USD',
44
+ proxyAddress: '0x10C8264C0935b3B9870013e057f330Ff3e9C56dC',
45
+ decimals: 8,
46
+ },
47
+ ];
48
+ /** Map short token name -> token metadata. */
49
+ exports.TOKEN_BY_SHORT = new Map(exports.SUPPORTED_TOKENS.map((t) => [t.short, t]));
50
+ /** Map pair string (e.g. "ETH/USD") -> token metadata. */
51
+ exports.TOKEN_BY_PAIR = new Map(exports.SUPPORTED_TOKENS.map((t) => [t.pair, t]));
@@ -0,0 +1,6 @@
1
+ export type { IDataFeed, IFeedNormalizer } from './interfaces';
2
+ export { BaseDataFeed } from './base-feed';
3
+ export type { DataFeedOptions } from './base-feed';
4
+ export type { Dictionary, Ticker, Tickers, OHLCV, OrderBook as FeedOrderBook, Market as FeedMarket, FundingRate, FundingRates, OracleRound, OracleParams, } from './types';
5
+ export * from './binance';
6
+ export * from './chainlink';
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.BaseDataFeed = void 0;
18
+ var base_feed_1 = require("./base-feed");
19
+ Object.defineProperty(exports, "BaseDataFeed", { enumerable: true, get: function () { return base_feed_1.BaseDataFeed; } });
20
+ __exportStar(require("./binance"), exports);
21
+ __exportStar(require("./chainlink"), exports);
@@ -0,0 +1,23 @@
1
+ import { Ticker, Tickers, OHLCV, OrderBook, Market, FundingRate, FundingRates, OracleRound, OracleParams, Dictionary } from './types';
2
+ export interface IDataFeed {
3
+ readonly name: string;
4
+ readonly description: string;
5
+ loadMarkets(reload?: boolean): Promise<Dictionary<Market>>;
6
+ fetchTicker(symbol: string): Promise<Ticker>;
7
+ fetchTickers(symbols?: string[]): Promise<Tickers>;
8
+ watchTicker(symbol: string, callback: (ticker: Ticker) => void): () => void;
9
+ fetchOHLCV(symbol: string, timeframe?: string, since?: number, limit?: number): Promise<OHLCV[]>;
10
+ fetchOrderBook?(symbol: string, limit?: number): Promise<OrderBook>;
11
+ watchOrderBook?(symbol: string, callback: (book: OrderBook) => void): () => void;
12
+ fetchFundingRate?(symbol: string): Promise<FundingRate>;
13
+ fetchFundingRates?(symbols?: string[]): Promise<FundingRates>;
14
+ fetchOracleRound?(params: OracleParams): Promise<OracleRound>;
15
+ fetchOracleHistory?(params: OracleParams): Promise<OracleRound[]>;
16
+ connect?(): Promise<void>;
17
+ close?(): Promise<void>;
18
+ }
19
+ export interface IFeedNormalizer<TRawTick = unknown, TRawCandle = unknown, TRawBook = unknown> {
20
+ normalizeTicker(raw: TRawTick): Ticker;
21
+ normalizeOHLCV?(raw: TRawCandle): OHLCV;
22
+ normalizeOrderBook?(raw: TRawBook): OrderBook;
23
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,123 @@
1
+ export interface Dictionary<T> {
2
+ [key: string]: T;
3
+ }
4
+ /**
5
+ * CCXT-compatible Ticker structure.
6
+ * Fields that a feed cannot populate are left undefined.
7
+ */
8
+ export interface Ticker {
9
+ symbol: string;
10
+ info: any;
11
+ timestamp: number | undefined;
12
+ datetime: string | undefined;
13
+ high: number | undefined;
14
+ low: number | undefined;
15
+ bid: number | undefined;
16
+ bidVolume: number | undefined;
17
+ ask: number | undefined;
18
+ askVolume: number | undefined;
19
+ vwap: number | undefined;
20
+ open: number | undefined;
21
+ close: number | undefined;
22
+ last: number | undefined;
23
+ previousClose: number | undefined;
24
+ change: number | undefined;
25
+ percentage: number | undefined;
26
+ average: number | undefined;
27
+ quoteVolume: number | undefined;
28
+ baseVolume: number | undefined;
29
+ indexPrice: number | undefined;
30
+ markPrice: number | undefined;
31
+ }
32
+ export type Tickers = Dictionary<Ticker>;
33
+ /**
34
+ * CCXT-compatible OHLCV tuple.
35
+ * [timestamp, open, high, low, close, volume]
36
+ */
37
+ export type OHLCV = [number, number, number, number, number, number];
38
+ /**
39
+ * CCXT-compatible OrderBook structure.
40
+ */
41
+ export interface OrderBook {
42
+ asks: [number, number][];
43
+ bids: [number, number][];
44
+ datetime: string | undefined;
45
+ timestamp: number | undefined;
46
+ nonce: number | undefined;
47
+ symbol: string | undefined;
48
+ }
49
+ /**
50
+ * CCXT-compatible Market structure (simplified for feeds).
51
+ */
52
+ export interface Market {
53
+ id: string;
54
+ symbol: string;
55
+ base: string;
56
+ quote: string;
57
+ active: boolean;
58
+ type: string;
59
+ spot: boolean;
60
+ margin: boolean;
61
+ swap: boolean;
62
+ future: boolean;
63
+ option: boolean;
64
+ contract: boolean;
65
+ precision: {
66
+ amount: number | undefined;
67
+ price: number | undefined;
68
+ };
69
+ limits: {
70
+ amount?: {
71
+ min: number | undefined;
72
+ max: number | undefined;
73
+ };
74
+ cost?: {
75
+ min: number | undefined;
76
+ max: number | undefined;
77
+ };
78
+ price?: {
79
+ min: number | undefined;
80
+ max: number | undefined;
81
+ };
82
+ };
83
+ info: any;
84
+ }
85
+ /**
86
+ * CCXT-compatible FundingRate structure.
87
+ */
88
+ export interface FundingRate {
89
+ symbol: string;
90
+ info: any;
91
+ timestamp?: number;
92
+ datetime?: string;
93
+ fundingRate?: number;
94
+ markPrice?: number;
95
+ indexPrice?: number;
96
+ interestRate?: number;
97
+ fundingTimestamp?: number;
98
+ fundingDatetime?: string;
99
+ nextFundingTimestamp?: number;
100
+ nextFundingDatetime?: string;
101
+ nextFundingRate?: number;
102
+ previousFundingRate?: number;
103
+ interval?: string;
104
+ }
105
+ export type FundingRates = Dictionary<FundingRate>;
106
+ /**
107
+ * ChainLink oracle price round (pmxt-specific).
108
+ */
109
+ export interface OracleRound {
110
+ feed: string;
111
+ roundId: string;
112
+ answer: number;
113
+ startedAt: number;
114
+ updatedAt: number;
115
+ answeredInRound: string;
116
+ decimals: number;
117
+ description?: string;
118
+ }
119
+ export interface OracleParams {
120
+ feed: string;
121
+ roundId?: string;
122
+ limit?: number;
123
+ }