oilpriceapi 0.8.2 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -19
- package/dist/cjs/client.js +139 -19
- package/dist/cjs/index.js +17 -3
- package/dist/cjs/resources/analytics.js +99 -137
- package/dist/cjs/resources/bunker-fuels.js +37 -23
- package/dist/cjs/resources/data-sources.js +13 -12
- package/dist/cjs/resources/ei/frac-focus.js +16 -6
- package/dist/cjs/resources/ei/well-permits.js +18 -6
- package/dist/cjs/resources/forecasts.js +11 -5
- package/dist/cjs/resources/futures.js +192 -1
- package/dist/cjs/resources/indicators.js +79 -0
- package/dist/cjs/resources/raw.js +128 -0
- package/dist/cjs/resources/rig-counts.js +5 -2
- package/dist/cjs/resources/spreads.js +105 -0
- package/dist/cjs/resources/storage.js +5 -5
- package/dist/cjs/resources/streaming.js +350 -0
- package/dist/cjs/resources/webhooks.js +3 -14
- package/dist/cjs/version.js +1 -1
- package/dist/client.d.ts +97 -1
- package/dist/client.js +139 -19
- package/dist/index.d.ts +12 -3
- package/dist/index.js +5 -0
- package/dist/resources/analytics.d.ts +147 -214
- package/dist/resources/analytics.js +99 -137
- package/dist/resources/bunker-fuels.d.ts +35 -12
- package/dist/resources/bunker-fuels.js +37 -23
- package/dist/resources/data-sources.d.ts +31 -31
- package/dist/resources/data-sources.js +13 -12
- package/dist/resources/ei/frac-focus.d.ts +23 -9
- package/dist/resources/ei/frac-focus.js +16 -6
- package/dist/resources/ei/well-permits.d.ts +25 -9
- package/dist/resources/ei/well-permits.js +18 -6
- package/dist/resources/forecasts.d.ts +4 -1
- package/dist/resources/forecasts.js +11 -5
- package/dist/resources/futures.d.ts +178 -1
- package/dist/resources/futures.js +190 -0
- package/dist/resources/indicators.d.ts +170 -0
- package/dist/resources/indicators.js +75 -0
- package/dist/resources/raw.d.ts +94 -0
- package/dist/resources/raw.js +124 -0
- package/dist/resources/rig-counts.js +5 -2
- package/dist/resources/spreads.d.ts +121 -0
- package/dist/resources/spreads.js +101 -0
- package/dist/resources/storage.d.ts +5 -4
- package/dist/resources/storage.js +5 -5
- package/dist/resources/streaming.d.ts +272 -0
- package/dist/resources/streaming.js +342 -0
- package/dist/resources/webhooks.d.ts +37 -23
- package/dist/resources/webhooks.js +3 -14
- package/dist/types.d.ts +41 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +7 -1
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spreads Resource
|
|
3
|
+
*
|
|
4
|
+
* Access oil & product spread analytics: crack spreads, basis spreads,
|
|
5
|
+
* curve-structure (contango/backwardation), refining margins, and physical
|
|
6
|
+
* premiums. Each spread type supports the latest value, full history, and an
|
|
7
|
+
* `all` listing.
|
|
8
|
+
*/
|
|
9
|
+
import { ValidationError } from "../errors.js";
|
|
10
|
+
/**
|
|
11
|
+
* Spreads Resource
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { OilPriceAPI } from 'oilpriceapi';
|
|
16
|
+
*
|
|
17
|
+
* const client = new OilPriceAPI({ apiKey: 'your_key' });
|
|
18
|
+
*
|
|
19
|
+
* // Latest crack spread
|
|
20
|
+
* const crack = await client.spreads.crack();
|
|
21
|
+
* console.log(`Crack spread: ${crack.value} ${crack.unit}`);
|
|
22
|
+
*
|
|
23
|
+
* // Historical basis spreads
|
|
24
|
+
* const history = await client.spreads.historical('basis', {
|
|
25
|
+
* startDate: '2024-01-01',
|
|
26
|
+
* endDate: '2024-12-31',
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // All margin spreads
|
|
30
|
+
* const all = await client.spreads.all('margin');
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export class SpreadsResource {
|
|
34
|
+
constructor(client) {
|
|
35
|
+
this.client = client;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get the latest value for a spread type.
|
|
39
|
+
*
|
|
40
|
+
* @param type - Spread type slug.
|
|
41
|
+
* @returns Latest spread value.
|
|
42
|
+
* @throws {ValidationError} If the type is invalid.
|
|
43
|
+
*/
|
|
44
|
+
async get(type) {
|
|
45
|
+
this.validateType(type);
|
|
46
|
+
return this.client["request"](`/v1/spreads/${type}`, {});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get historical data for a spread type.
|
|
50
|
+
*
|
|
51
|
+
* @param type - Spread type slug.
|
|
52
|
+
* @param options - Optional date range filters.
|
|
53
|
+
* @returns Array of historical spread values.
|
|
54
|
+
*/
|
|
55
|
+
async historical(type, options) {
|
|
56
|
+
this.validateType(type);
|
|
57
|
+
const params = {};
|
|
58
|
+
if (options?.startDate)
|
|
59
|
+
params.start_date = options.startDate;
|
|
60
|
+
if (options?.endDate)
|
|
61
|
+
params.end_date = options.endDate;
|
|
62
|
+
const response = await this.client["request"](`/v1/spreads/${type}/historical`, params);
|
|
63
|
+
return Array.isArray(response) ? response : response.data;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get all spread values for a spread type.
|
|
67
|
+
*
|
|
68
|
+
* @param type - Spread type slug.
|
|
69
|
+
* @returns Array of spread values.
|
|
70
|
+
*/
|
|
71
|
+
async all(type) {
|
|
72
|
+
this.validateType(type);
|
|
73
|
+
const response = await this.client["request"](`/v1/spreads/${type}/all`, {});
|
|
74
|
+
return Array.isArray(response) ? response : response.data;
|
|
75
|
+
}
|
|
76
|
+
/** Latest crack spread. */
|
|
77
|
+
async crack() {
|
|
78
|
+
return this.get("crack");
|
|
79
|
+
}
|
|
80
|
+
/** Latest basis spread. */
|
|
81
|
+
async basis() {
|
|
82
|
+
return this.get("basis");
|
|
83
|
+
}
|
|
84
|
+
/** Latest curve-structure (contango / backwardation). */
|
|
85
|
+
async curveStructure() {
|
|
86
|
+
return this.get("curve-structure");
|
|
87
|
+
}
|
|
88
|
+
/** Latest refining margin. */
|
|
89
|
+
async margin() {
|
|
90
|
+
return this.get("margin");
|
|
91
|
+
}
|
|
92
|
+
/** Latest physical premium. */
|
|
93
|
+
async physicalPremium() {
|
|
94
|
+
return this.get("physical-premium");
|
|
95
|
+
}
|
|
96
|
+
validateType(type) {
|
|
97
|
+
if (!type || typeof type !== "string") {
|
|
98
|
+
throw new ValidationError("Spread type must be a non-empty string");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -43,10 +43,11 @@ export interface HistoricalStorageData {
|
|
|
43
43
|
* Options for historical storage query
|
|
44
44
|
*/
|
|
45
45
|
export interface HistoricalStorageOptions {
|
|
46
|
-
/**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Lookback period. The API reads a `period` token, one of
|
|
48
|
+
* '7d' | '30d' | '90d' (default) | '1y' | 'all' — not arbitrary date ranges.
|
|
49
|
+
*/
|
|
50
|
+
period?: "7d" | "30d" | "90d" | "1y" | "all";
|
|
50
51
|
}
|
|
51
52
|
/**
|
|
52
53
|
* Storage Resource
|
|
@@ -152,11 +152,11 @@ export class StorageResource {
|
|
|
152
152
|
throw new ValidationError("Storage location code must be a non-empty string");
|
|
153
153
|
}
|
|
154
154
|
const params = {};
|
|
155
|
-
if (options?.
|
|
156
|
-
params.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const response = await this.client["request"](`/v1/storage/${code}
|
|
155
|
+
if (options?.period)
|
|
156
|
+
params.period = options.period;
|
|
157
|
+
// Route is GET /v1/storage/history/:code (the :code segment comes AFTER
|
|
158
|
+
// `history`), and the controller reads a `period` token.
|
|
159
|
+
const response = await this.client["request"](`/v1/storage/history/${code}`, params);
|
|
160
160
|
return Array.isArray(response) ? response : response.data;
|
|
161
161
|
}
|
|
162
162
|
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket Streaming Resource
|
|
3
|
+
*
|
|
4
|
+
* Real-time price streaming via the OilPriceAPI ActionCable endpoint
|
|
5
|
+
* (`wss://api.oilpriceapi.com/cable`).
|
|
6
|
+
*
|
|
7
|
+
* Streaming is a **Reservoir Mastery (Professional+)** feature. Connections
|
|
8
|
+
* authenticate with your API key and subscribe to the `EnergyPricesChannel`,
|
|
9
|
+
* which pushes an initial `welcome` snapshot followed by live `price_update`
|
|
10
|
+
* and (for drilling-tier accounts) `rig_count_update` messages.
|
|
11
|
+
*
|
|
12
|
+
* The implementation speaks the raw ActionCable JSON subprotocol over the
|
|
13
|
+
* `ws` package: it performs the `welcome` -> `subscribe` ->
|
|
14
|
+
* `confirm_subscription` handshake, answers server `ping` frames, and
|
|
15
|
+
* surfaces decoded channel messages as typed events. Auto-reconnect with
|
|
16
|
+
* exponential backoff keeps the stream alive across transient network drops.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const sub = client.stream.prices({}, (update) => {
|
|
21
|
+
* console.log(update.prices.oil.wti?.original_price);
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* sub.on("rig_count_update", (m) => console.log(m.rig_count.region, m.rig_count.count));
|
|
25
|
+
* sub.on("error", (err) => console.error(err));
|
|
26
|
+
*
|
|
27
|
+
* // later
|
|
28
|
+
* sub.close();
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
import { EventEmitter } from "node:events";
|
|
32
|
+
import WebSocket from "ws";
|
|
33
|
+
import type { OilPriceAPI } from "../client.js";
|
|
34
|
+
/**
|
|
35
|
+
* The ActionCable channel exposed by the OilPriceAPI server.
|
|
36
|
+
*
|
|
37
|
+
* Confirmed from `app/channels/energy_prices_channel.rb`
|
|
38
|
+
* (`class EnergyPricesChannel`).
|
|
39
|
+
*/
|
|
40
|
+
export declare const ENERGY_PRICES_CHANNEL = "EnergyPricesChannel";
|
|
41
|
+
/**
|
|
42
|
+
* A single normalized price point as broadcast by the server.
|
|
43
|
+
*
|
|
44
|
+
* Mirrors the shape produced by `BroadcastEnergyPricesJob#normalized_price_for_cached`
|
|
45
|
+
* and `EnergyPricesChannel#normalize_price`.
|
|
46
|
+
*/
|
|
47
|
+
export interface StreamedPrice {
|
|
48
|
+
/** Price converted to the common base unit (USD / MMBtu). */
|
|
49
|
+
normalized_price: number | null;
|
|
50
|
+
/** Original price in its native unit/currency. */
|
|
51
|
+
original_price: number | null;
|
|
52
|
+
/** Native unit (e.g. `"barrel_oil"`, `"mmbtu"`). */
|
|
53
|
+
original_unit: string;
|
|
54
|
+
/** Native currency (e.g. `"USD"`, `"GBP"`, `"EUR"`). */
|
|
55
|
+
original_currency: string;
|
|
56
|
+
/** ISO-8601 timestamp of the underlying price record. */
|
|
57
|
+
timestamp: string;
|
|
58
|
+
/** 24h absolute change (present on the initial `welcome` snapshot). */
|
|
59
|
+
change_24h?: number;
|
|
60
|
+
/** 24h percent change (present on the initial `welcome` snapshot). */
|
|
61
|
+
change_24h_percent?: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The `prices` map carried by `welcome` and `price_update` messages.
|
|
65
|
+
*/
|
|
66
|
+
export interface StreamedPriceMap {
|
|
67
|
+
oil: {
|
|
68
|
+
brent: StreamedPrice | null;
|
|
69
|
+
wti: StreamedPrice | null;
|
|
70
|
+
};
|
|
71
|
+
natural_gas: {
|
|
72
|
+
uk: StreamedPrice | null;
|
|
73
|
+
us: StreamedPrice | null;
|
|
74
|
+
eu: StreamedPrice | null;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Live `price_update` broadcast (the most common streamed message).
|
|
79
|
+
*/
|
|
80
|
+
export interface PriceUpdateMessage {
|
|
81
|
+
type: "price_update";
|
|
82
|
+
timestamp: string;
|
|
83
|
+
base_currency: string;
|
|
84
|
+
base_unit: string;
|
|
85
|
+
prices: StreamedPriceMap;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Initial snapshot transmitted immediately on subscription confirmation.
|
|
89
|
+
*
|
|
90
|
+
* Note: the server uses `type: "welcome"` for this *channel* message. It is
|
|
91
|
+
* distinct from the ActionCable transport-level `welcome` frame, which the
|
|
92
|
+
* client consumes internally and never surfaces.
|
|
93
|
+
*/
|
|
94
|
+
export interface WelcomeMessage {
|
|
95
|
+
type: "welcome";
|
|
96
|
+
data: {
|
|
97
|
+
timestamp?: string;
|
|
98
|
+
base_currency?: string;
|
|
99
|
+
base_unit?: string;
|
|
100
|
+
prices?: StreamedPriceMap;
|
|
101
|
+
/** Present only for drilling-tier accounts. */
|
|
102
|
+
drilling_intelligence?: Record<string, unknown>;
|
|
103
|
+
/** Present when the initial snapshot could not be built. */
|
|
104
|
+
error?: string;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Rig-count update broadcast (drilling / Reservoir Mastery accounts).
|
|
109
|
+
*/
|
|
110
|
+
export interface RigCountUpdateMessage {
|
|
111
|
+
type: "rig_count_update";
|
|
112
|
+
timestamp: string;
|
|
113
|
+
rig_count: {
|
|
114
|
+
code: string;
|
|
115
|
+
region: string;
|
|
116
|
+
count: number;
|
|
117
|
+
source: string;
|
|
118
|
+
updated_at: string;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Any decoded channel message. Unknown `type` values are passed through so
|
|
123
|
+
* forward-compatible servers don't break older SDKs.
|
|
124
|
+
*/
|
|
125
|
+
export type StreamMessage = WelcomeMessage | PriceUpdateMessage | RigCountUpdateMessage | {
|
|
126
|
+
type: string;
|
|
127
|
+
[key: string]: unknown;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Options for {@link StreamingResource.prices}.
|
|
131
|
+
*/
|
|
132
|
+
export interface StreamPricesOptions {
|
|
133
|
+
/**
|
|
134
|
+
* Optional client-side filter. When provided, only `price_update` messages
|
|
135
|
+
* whose normalized map contains at least one of these commodity slugs are
|
|
136
|
+
* delivered to `onUpdate` / the `price_update` event.
|
|
137
|
+
*
|
|
138
|
+
* Accepts the streamed slugs (`"brent"`, `"wti"`, `"uk"`, `"us"`, `"eu"`)
|
|
139
|
+
* or the upstream codes (`"BRENT_CRUDE_USD"`, `"WTI_USD"`,
|
|
140
|
+
* `"NATURAL_GAS_GBP"`, `"NATURAL_GAS_USD"`, `"DUTCH_TTF_EUR"`).
|
|
141
|
+
*
|
|
142
|
+
* The server broadcasts the full map regardless; filtering is applied
|
|
143
|
+
* locally so callers can scope updates without extra config.
|
|
144
|
+
*/
|
|
145
|
+
commodities?: string[];
|
|
146
|
+
/** Disable automatic reconnection (default: reconnect enabled). */
|
|
147
|
+
autoReconnect?: boolean;
|
|
148
|
+
/** Base reconnect delay in ms (default: 1000). */
|
|
149
|
+
reconnectDelay?: number;
|
|
150
|
+
/** Maximum reconnect delay in ms for the exponential backoff (default: 30000). */
|
|
151
|
+
maxReconnectDelay?: number;
|
|
152
|
+
/**
|
|
153
|
+
* Maximum number of consecutive reconnect attempts before giving up and
|
|
154
|
+
* emitting a terminal `error`. `Infinity` to retry forever (default: 10).
|
|
155
|
+
*/
|
|
156
|
+
maxReconnectAttempts?: number;
|
|
157
|
+
}
|
|
158
|
+
/** Callback invoked for each delivered `price_update` message. */
|
|
159
|
+
export type PriceUpdateHandler = (update: PriceUpdateMessage) => void;
|
|
160
|
+
/**
|
|
161
|
+
* Handle for an active price stream.
|
|
162
|
+
*
|
|
163
|
+
* Extends `EventEmitter`. Emitted events:
|
|
164
|
+
* - `"connected"` — transport connected and subscription confirmed
|
|
165
|
+
* - `"welcome"` — initial snapshot ({@link WelcomeMessage})
|
|
166
|
+
* - `"price_update"` — live price broadcast ({@link PriceUpdateMessage})
|
|
167
|
+
* - `"rig_count_update"` — drilling broadcast ({@link RigCountUpdateMessage})
|
|
168
|
+
* - `"message"` — every decoded channel message ({@link StreamMessage})
|
|
169
|
+
* - `"reconnecting"` — a reconnect attempt is scheduled (`{ attempt, delay }`)
|
|
170
|
+
* - `"disconnected"` — transport closed (`{ code, reason }`)
|
|
171
|
+
* - `"error"` — an `Error` (transport error, unauthorized, or retries exhausted)
|
|
172
|
+
* - `"close"` — the subscription was closed via {@link PriceStreamSubscription.close}
|
|
173
|
+
*/
|
|
174
|
+
export declare class PriceStreamSubscription extends EventEmitter {
|
|
175
|
+
private readonly wsImpl;
|
|
176
|
+
private ws;
|
|
177
|
+
private readonly url;
|
|
178
|
+
private readonly apiKey;
|
|
179
|
+
private readonly identifier;
|
|
180
|
+
private readonly options;
|
|
181
|
+
private readonly commodityFilter;
|
|
182
|
+
private closed;
|
|
183
|
+
private subscribed;
|
|
184
|
+
private reconnectAttempts;
|
|
185
|
+
private reconnectTimer;
|
|
186
|
+
/**
|
|
187
|
+
* @param url - The `wss://.../cable` endpoint.
|
|
188
|
+
* @param apiKey - API key sent as the ActionCable `Authorization: Token <key>` header.
|
|
189
|
+
* @param options - Reconnect + filter options.
|
|
190
|
+
* @param wsImpl - Injectable WebSocket constructor (used by tests to mock).
|
|
191
|
+
* @internal Construct via {@link StreamingResource.prices}.
|
|
192
|
+
*/
|
|
193
|
+
constructor(url: string, apiKey: string, options: StreamPricesOptions, wsImpl?: typeof WebSocket);
|
|
194
|
+
/**
|
|
195
|
+
* Open the transport and begin the ActionCable handshake.
|
|
196
|
+
* @internal Called once by {@link StreamingResource.prices}.
|
|
197
|
+
*/
|
|
198
|
+
connect(): void;
|
|
199
|
+
private handleRaw;
|
|
200
|
+
private dispatch;
|
|
201
|
+
private matchesFilter;
|
|
202
|
+
private scheduleReconnect;
|
|
203
|
+
private send;
|
|
204
|
+
/** Whether the channel subscription has been confirmed by the server. */
|
|
205
|
+
get isSubscribed(): boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Cleanly tear down the stream: cancels any pending reconnect, unsubscribes
|
|
208
|
+
* from the channel, and closes the socket. Safe to call multiple times.
|
|
209
|
+
* Emits `"close"` once.
|
|
210
|
+
*/
|
|
211
|
+
close(): void;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Streaming resource — entry point for real-time price subscriptions.
|
|
215
|
+
*
|
|
216
|
+
* Accessed via `client.stream`.
|
|
217
|
+
*/
|
|
218
|
+
export declare class StreamingResource {
|
|
219
|
+
private client;
|
|
220
|
+
/**
|
|
221
|
+
* Injectable WebSocket implementation. Defaults to the `ws` package;
|
|
222
|
+
* tests pass a mock constructor.
|
|
223
|
+
* @internal
|
|
224
|
+
*/
|
|
225
|
+
private wsImpl;
|
|
226
|
+
constructor(client: OilPriceAPI,
|
|
227
|
+
/**
|
|
228
|
+
* Injectable WebSocket implementation. Defaults to the `ws` package;
|
|
229
|
+
* tests pass a mock constructor.
|
|
230
|
+
* @internal
|
|
231
|
+
*/
|
|
232
|
+
wsImpl?: typeof WebSocket);
|
|
233
|
+
/**
|
|
234
|
+
* Derive the `wss://.../cable` endpoint from the client's REST base URL.
|
|
235
|
+
*
|
|
236
|
+
* `https://api.oilpriceapi.com` -> `wss://api.oilpriceapi.com/cable`
|
|
237
|
+
* `http://localhost:5000` -> `ws://localhost:5000/cable`
|
|
238
|
+
*/
|
|
239
|
+
private cableUrl;
|
|
240
|
+
/**
|
|
241
|
+
* Open a real-time price stream over the `EnergyPricesChannel`.
|
|
242
|
+
*
|
|
243
|
+
* Returns a {@link PriceStreamSubscription} handle (an `EventEmitter`) you
|
|
244
|
+
* can attach further listeners to and `.close()` when done. The optional
|
|
245
|
+
* `onUpdate` callback is a convenience wired to the `price_update` event.
|
|
246
|
+
*
|
|
247
|
+
* @param options - Filtering and reconnect options.
|
|
248
|
+
* @param onUpdate - Optional callback for each `price_update` message.
|
|
249
|
+
* @returns The subscription handle.
|
|
250
|
+
*
|
|
251
|
+
* @throws {OilPriceAPIError} If no API key is configured on the client.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```typescript
|
|
255
|
+
* const client = new OilPriceAPI({ apiKey: process.env.OILPRICEAPI_KEY });
|
|
256
|
+
*
|
|
257
|
+
* const sub = client.stream.prices(
|
|
258
|
+
* { commodities: ["WTI_USD", "BRENT_CRUDE_USD"] },
|
|
259
|
+
* (update) => {
|
|
260
|
+
* const wti = update.prices.oil.wti;
|
|
261
|
+
* if (wti) console.log(`WTI ${wti.original_price} @ ${update.timestamp}`);
|
|
262
|
+
* },
|
|
263
|
+
* );
|
|
264
|
+
*
|
|
265
|
+
* sub.on("connected", () => console.log("streaming live"));
|
|
266
|
+
* sub.on("error", (err) => console.error("stream error:", err));
|
|
267
|
+
*
|
|
268
|
+
* process.on("SIGINT", () => sub.close());
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
271
|
+
prices(options?: StreamPricesOptions, onUpdate?: PriceUpdateHandler): PriceStreamSubscription;
|
|
272
|
+
}
|