@qtsurfer/api-client 0.20.0 → 0.21.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.
@@ -115,6 +115,9 @@ import type {
115
115
  ListPublicLiveData,
116
116
  ListPublicLiveResponse,
117
117
  ListPublicLiveError,
118
+ GetLiveRunData,
119
+ GetLiveRunResponse,
120
+ GetLiveRunError,
118
121
  UpdateLiveData,
119
122
  UpdateLiveResponse,
120
123
  UpdateLiveError,
@@ -124,6 +127,12 @@ import type {
124
127
  SendLiveCommandData,
125
128
  SendLiveCommandResponse,
126
129
  SendLiveCommandError,
130
+ RevokeLiveStreamData,
131
+ RevokeLiveStreamResponse,
132
+ RevokeLiveStreamError,
133
+ RotateLiveStreamData,
134
+ RotateLiveStreamResponse,
135
+ RotateLiveStreamError,
127
136
  GetLiveRunSignalsData,
128
137
  GetLiveRunSignalsResponse,
129
138
  GetLiveRunSignalsError,
@@ -1289,7 +1298,8 @@ export const getDatasetImport = <ThrowOnError extends boolean = false>(
1289
1298
  * Requests a stop. The run winds down at its own next check-in rather than instantly —
1290
1299
  * poll `GET`/`PATCH` `.../live` and expect `state` to remain `RUNNING` for a short window
1291
1300
  * after `desired` flips to `STOPPED`. Calling this again on an already-stopped run is not an
1292
- * error; it returns the same (unchanged) state.
1301
+ * error; it returns the same (unchanged) state. A stopped run has no stream: its `streamUrl`, if it had one,
1302
+ * stops working and is not in this response.
1293
1303
  *
1294
1304
  */
1295
1305
  export const stopLive = <ThrowOnError extends boolean = false>(
@@ -1315,7 +1325,12 @@ export const stopLive = <ThrowOnError extends boolean = false>(
1315
1325
  * Get this strategy's current (or most recent) live run
1316
1326
  * The run you last started for this strategy — its most complete state, including `params`
1317
1327
  * and the promotion `gate` once the sandbox trial has one to report. Returns the run's last
1318
- * known state even after it has stopped; this endpoint never disappears history.
1328
+ * known state even after it has stopped; this endpoint never disappears history. When the run was started
1329
+ * with a `stream`, `streamUrl` is here too while the run is running and your plan allows it.
1330
+ *
1331
+ * While the run is being executed it also carries `stats`, the run's latest counters (updates
1332
+ * processed, rate, instruments seen), refreshed about once a minute. Starting or stopping a run
1333
+ * does not return them; read them here.
1319
1334
  *
1320
1335
  */
1321
1336
  export const getLive = <ThrowOnError extends boolean = false>(
@@ -1372,6 +1387,11 @@ export const getLive = <ThrowOnError extends boolean = false>(
1372
1387
  * (it overrides `getExecutionCallback()`) has no other execution venue, so it cannot start
1373
1388
  * without a `paper` block.
1374
1389
  *
1390
+ * **A plain WebSocket stream.** Pass `stream: true` to get a secret URL for this run's signals that a simple
1391
+ * client, or a service that passes them on to others, can open as an ordinary WebSocket, from the sandbox stage
1392
+ * on. The URL is in the response (`streamUrl`) and in `GET /strategy/{strategyId}/live`; treat it like a
1393
+ * password. See the "Live execution" guide.
1394
+ *
1375
1395
  */
1376
1396
  export const startLive = <ThrowOnError extends boolean = false>(
1377
1397
  options: Options<StartLiveData, ThrowOnError>
@@ -1444,6 +1464,40 @@ export const listPublicLive = <ThrowOnError extends boolean = false>(
1444
1464
  });
1445
1465
  };
1446
1466
 
1467
+ /**
1468
+ * Read one of your runs by its id
1469
+ * Owner only, addressed by `runId` directly rather than through its strategy: the run's own
1470
+ * canonical identity, which is what `POST`/`GET`/`DELETE` `.../live`, `GET /live` and
1471
+ * `GET /live/public` all hand out. Use it to re-read one specific run — including one you
1472
+ * stopped long ago or that is no longer your strategy's most recent — without paging through
1473
+ * `GET /live`.
1474
+ *
1475
+ * Returns the same state as `GET /strategy/{strategyId}/live` (`strategyId` is the strategy's
1476
+ * id, and `stats` is there too), plus `updatedAtMs`: when the run last changed, from any cause — a
1477
+ * state change, a promotion, a parameter update, a stop. A refresh of `stats` is not a change of
1478
+ * the run and does not move `updatedAtMs`. A run that is public is reachable by others through
1479
+ * `GET /live/public`, never through this route.
1480
+ *
1481
+ */
1482
+ export const getLiveRun = <ThrowOnError extends boolean = false>(
1483
+ options: Options<GetLiveRunData, ThrowOnError>
1484
+ ) => {
1485
+ return (options.client ?? _heyApiClient).get<
1486
+ GetLiveRunResponse,
1487
+ GetLiveRunError,
1488
+ ThrowOnError
1489
+ >({
1490
+ security: [
1491
+ {
1492
+ scheme: "bearer",
1493
+ type: "http",
1494
+ },
1495
+ ],
1496
+ url: "/live/{runId}",
1497
+ ...options,
1498
+ });
1499
+ };
1500
+
1447
1501
  /**
1448
1502
  * Change a run's visibility, name, or description
1449
1503
  * Owner only, addressed by `runId` directly rather than through its strategy — this is a
@@ -1555,6 +1609,63 @@ export const sendLiveCommand = <ThrowOnError extends boolean = false>(
1555
1609
  });
1556
1610
  };
1557
1611
 
1612
+ /**
1613
+ * Revoke a run's stream URL
1614
+ * Revokes a run's stream URL **for good**: connections open on it are closed within about 15 seconds and it
1615
+ * answers `404` from then on. The run itself is not touched, and a stream cannot be added to it again; start
1616
+ * the run again with `stream: true` for a new URL. Owner only, and always allowed, whatever your plan or the
1617
+ * run's state. Repeating it is not an error.
1618
+ *
1619
+ */
1620
+ export const revokeLiveStream = <ThrowOnError extends boolean = false>(
1621
+ options: Options<RevokeLiveStreamData, ThrowOnError>
1622
+ ) => {
1623
+ return (options.client ?? _heyApiClient).delete<
1624
+ RevokeLiveStreamResponse,
1625
+ RevokeLiveStreamError,
1626
+ ThrowOnError
1627
+ >({
1628
+ security: [
1629
+ {
1630
+ scheme: "bearer",
1631
+ type: "http",
1632
+ },
1633
+ ],
1634
+ url: "/live/{runId}/stream",
1635
+ ...options,
1636
+ });
1637
+ };
1638
+
1639
+ /**
1640
+ * Rotate a run's stream URL
1641
+ * Gives a run a **new** stream URL and retires the old one: connections open on the old URL are closed
1642
+ * within about 15 seconds and the old URL answers `404` from then on. Use it when the URL may have leaked.
1643
+ * Owner only, and only for a run that is running and was started with `stream: true` (the URL cannot be added
1644
+ * to a run later, and a revoked one cannot be brought back). The plan is checked again: a plan that may not
1645
+ * broadcast gets `429`.
1646
+ *
1647
+ * See the "Live execution" guide, "A plain WebSocket stream of a run".
1648
+ *
1649
+ */
1650
+ export const rotateLiveStream = <ThrowOnError extends boolean = false>(
1651
+ options: Options<RotateLiveStreamData, ThrowOnError>
1652
+ ) => {
1653
+ return (options.client ?? _heyApiClient).post<
1654
+ RotateLiveStreamResponse,
1655
+ RotateLiveStreamError,
1656
+ ThrowOnError
1657
+ >({
1658
+ security: [
1659
+ {
1660
+ scheme: "bearer",
1661
+ type: "http",
1662
+ },
1663
+ ],
1664
+ url: "/live/{runId}/stream",
1665
+ ...options,
1666
+ });
1667
+ };
1668
+
1558
1669
  /**
1559
1670
  * Read a run's signals
1560
1671
  * Returns one page of the signals a run has already produced, newest-last, optionally from a
@@ -1821,6 +1821,16 @@ export type StartLiveRequest = {
1821
1821
  * Request that this run's signals be relayed over its WebSocket channel, from its first signal — in the `sandbox` stage too, where only you can subscribe to it. See the "Live execution" guide.
1822
1822
  */
1823
1823
  relay?: boolean;
1824
+ /**
1825
+ * Ask for a **stream URL**: a secret address that a simple client, or a service that passes your signals
1826
+ * on to others, can open as a plain WebSocket to receive this run's signals as they are produced, one JSON
1827
+ * text frame per signal, with none of the live-execution protocol around it. The URL comes back as
1828
+ * `streamUrl` in the response to this call. Available from the `sandbox` stage on, on the plans that may
1829
+ * broadcast; any other plan gets `429`. It can be asked for **only when the run is started** (not added
1830
+ * later), and it also turns `relay` on. See the "Live execution" guide, "A plain WebSocket stream of a run".
1831
+ *
1832
+ */
1833
+ stream?: boolean;
1824
1834
  name?: string;
1825
1835
  description?: string;
1826
1836
  paper?: LivePaperConfig;
@@ -1958,6 +1968,102 @@ export type LiveRun = {
1958
1968
  * The run's paper trading configuration as accepted at start, normalised. Absent when the run has no paper trading.
1959
1969
  */
1960
1970
  paper?: LivePaperConfig;
1971
+ /**
1972
+ * The run's latest counters. Returned by the two reads, `GET /strategy/{strategyId}/live` and
1973
+ * `GET /live/{runId}`; never by starting or stopping a run. Absent until the first snapshot exists
1974
+ * (a run that has just started), and absent is not zero.
1975
+ *
1976
+ */
1977
+ stats?: LiveRunStats;
1978
+ };
1979
+
1980
+ /**
1981
+ * What a run has been doing, as of its last snapshot. The platform refreshes it about once a minute
1982
+ * while the run is being executed, so `opsPerSecond` is an average over that interval, not an
1983
+ * instantaneous rate.
1984
+ *
1985
+ */
1986
+ export type LiveRunStats = {
1987
+ /**
1988
+ * Updates of instruments the run has accepted since it started executing. It can start again from zero if the run is restarted.
1989
+ */
1990
+ processed: number;
1991
+ /**
1992
+ * Updates accepted per second over the last refresh interval. `0` when none arrived.
1993
+ */
1994
+ opsPerSecond: number;
1995
+ /**
1996
+ * How many distinct instruments the run has received an update for.
1997
+ */
1998
+ instrumentsSeen: number;
1999
+ /**
2000
+ * Epoch milliseconds when these counters were last written.
2001
+ */
2002
+ asOfMs: number;
2003
+ /**
2004
+ * Epoch milliseconds of the last snapshot in which `processed` had grown. Absent until the run has
2005
+ * processed anything. A run fed by a source that updates rarely (a funding rate, for example) can
2006
+ * stay flat for hours: that is how such a run behaves, not a fault.
2007
+ *
2008
+ */
2009
+ progressedAtMs?: number;
2010
+ /**
2011
+ * `true` when the run is meant to be running (`desired` is `RUNNING`) and its counters have not
2012
+ * been refreshed for several refresh intervals: the platform has stopped updating them, which is
2013
+ * worth checking against `state`. `false` otherwise. A run whose `processed` is flat is not stale;
2014
+ * `progressedAtMs` is how to tell it apart.
2015
+ *
2016
+ */
2017
+ stale: boolean;
2018
+ };
2019
+
2020
+ /**
2021
+ * A run as returned by `GET /live/{runId}`, the full state of `LiveRun` plus when it last changed.
2022
+ */
2023
+ export type LiveRunDetail = LiveRun & {
2024
+ /**
2025
+ * Epoch milliseconds of the run's last change, from any cause. It only moves forward, so of two reads of the same run the one with the larger value is the newer.
2026
+ */
2027
+ updatedAtMs: number;
2028
+ };
2029
+
2030
+ /**
2031
+ * A run as `LiveRun` describes it, plus its `streamUrl` when it has one. It is what **starting a run** and
2032
+ * `GET /strategy/{strategyId}/live` return: your own run, read with your own credentials. Stopping a run
2033
+ * and `GET /live/{runId}` return `LiveRun`, which never carries the URL.
2034
+ *
2035
+ */
2036
+ export type LiveRunWithStream = LiveRun & {
2037
+ /**
2038
+ * The run's secret stream URL (`wss://…`). **Treat it like a password**: anyone who holds it can read
2039
+ * this run's signals, from the sandbox stage on. Present only when the run was started with
2040
+ * `stream: true`, is wanted running, has not had its stream revoked, and your plan still lets you
2041
+ * broadcast; absent otherwise (a plan that lets you broadcast again gets the same URL back). Rotate
2042
+ * it with `POST /live/{runId}/stream` if it leaks, revoke it with `DELETE /live/{runId}/stream`.
2043
+ *
2044
+ */
2045
+ streamUrl?: string;
2046
+ };
2047
+
2048
+ /**
2049
+ * A run's new stream URL, as returned by `POST /live/{runId}/stream`.
2050
+ */
2051
+ export type LiveStreamUrl = {
2052
+ /**
2053
+ * The run's new secret stream URL. The previous one has stopped working.
2054
+ */
2055
+ streamUrl: string;
2056
+ };
2057
+
2058
+ /**
2059
+ * What `DELETE /live/{runId}/stream` returns.
2060
+ */
2061
+ export type LiveStreamRevoked = {
2062
+ runId: string;
2063
+ /**
2064
+ * Always `true`.
2065
+ */
2066
+ revoked: boolean;
1961
2067
  };
1962
2068
 
1963
2069
  /**
@@ -3698,9 +3804,9 @@ export type GetLiveError = GetLiveErrors[keyof GetLiveErrors];
3698
3804
 
3699
3805
  export type GetLiveResponses = {
3700
3806
  /**
3701
- * The run's current state
3807
+ * The run's current state, with its `streamUrl` when it has one
3702
3808
  */
3703
- 200: LiveRun;
3809
+ 200: LiveRunWithStream;
3704
3810
  };
3705
3811
 
3706
3812
  export type GetLiveResponse = GetLiveResponses[keyof GetLiveResponses];
@@ -3719,7 +3825,7 @@ export type StartLiveData = {
3719
3825
 
3720
3826
  export type StartLiveErrors = {
3721
3827
  /**
3722
- * Malformed `sources` (not exactly one entry, missing field, unsupported `type`), a `type` the strategy cannot consume (a ticker strategy with a `kline` source, or the reverse; the message names both), an invalid `visibility`, an invalid `paper` block (an unknown field, a wrong type or an out-of-range value), or no `paper` block for a strategy that listens to its own execution events.
3828
+ * Malformed `sources` (not exactly one entry, missing field, unsupported `type`), a `type` the strategy cannot consume (a ticker strategy with a `kline` source, or the reverse; the message names both), an invalid `visibility`, an invalid `paper` block (an unknown field, a wrong type or an out-of-range value), or no `paper` block for a strategy that listens to its own execution events. A `relay` or `stream` that is not `true` or `false`, or a `stream` where streams are not available yet.
3723
3829
  */
3724
3830
  400: ResponseError;
3725
3831
  /**
@@ -3731,9 +3837,10 @@ export type StartLiveErrors = {
3731
3837
  */
3732
3838
  409: ResponseError;
3733
3839
  /**
3734
- * Your plan does not include live runs, would exceed your concurrent-run or
3735
- * instrument-count limit, or the platform is at capacity right now. Carries a
3736
- * `Retry-After` header.
3840
+ * One of two kinds. **Your plan** does not include live runs, would exceed your concurrent-run or
3841
+ * instrument-count limit, or does not let you ask for a `stream`: the message names your plan, and
3842
+ * retrying will not help until something changes, so there is no `Retry-After`. Or **the platform is at
3843
+ * capacity** right now: a `Retry-After` header says when to try again.
3737
3844
  *
3738
3845
  */
3739
3846
  429: ResponseError;
@@ -3743,9 +3850,9 @@ export type StartLiveError = StartLiveErrors[keyof StartLiveErrors];
3743
3850
 
3744
3851
  export type StartLiveResponses = {
3745
3852
  /**
3746
- * Started — the run's own state, in the sandbox stage
3853
+ * Started — the run's own state, in the sandbox stage, with its `streamUrl` when you asked for a stream
3747
3854
  */
3748
- 201: LiveRun;
3855
+ 201: LiveRunWithStream;
3749
3856
  };
3750
3857
 
3751
3858
  export type StartLiveResponse = StartLiveResponses[keyof StartLiveResponses];
@@ -3820,6 +3927,36 @@ export type ListPublicLiveResponses = {
3820
3927
  export type ListPublicLiveResponse =
3821
3928
  ListPublicLiveResponses[keyof ListPublicLiveResponses];
3822
3929
 
3930
+ export type GetLiveRunData = {
3931
+ body?: never;
3932
+ path: {
3933
+ /**
3934
+ * The `runId` from `POST`/`GET`/`DELETE` `.../live`, from `GET /live` or from `GET /live/public`
3935
+ */
3936
+ runId: string;
3937
+ };
3938
+ query?: never;
3939
+ url: "/live/{runId}";
3940
+ };
3941
+
3942
+ export type GetLiveRunErrors = {
3943
+ /**
3944
+ * No such run, or you do not own it — the two look identical on purpose.
3945
+ */
3946
+ 404: ResponseError;
3947
+ };
3948
+
3949
+ export type GetLiveRunError = GetLiveRunErrors[keyof GetLiveRunErrors];
3950
+
3951
+ export type GetLiveRunResponses = {
3952
+ /**
3953
+ * The run
3954
+ */
3955
+ 200: LiveRunDetail;
3956
+ };
3957
+
3958
+ export type GetLiveRunResponse = GetLiveRunResponses[keyof GetLiveRunResponses];
3959
+
3823
3960
  export type UpdateLiveData = {
3824
3961
  body?: UpdateLiveRequest;
3825
3962
  path: {
@@ -3940,6 +4077,78 @@ export type SendLiveCommandResponses = {
3940
4077
  export type SendLiveCommandResponse =
3941
4078
  SendLiveCommandResponses[keyof SendLiveCommandResponses];
3942
4079
 
4080
+ export type RevokeLiveStreamData = {
4081
+ body?: never;
4082
+ path: {
4083
+ runId: string;
4084
+ };
4085
+ query?: never;
4086
+ url: "/live/{runId}/stream";
4087
+ };
4088
+
4089
+ export type RevokeLiveStreamErrors = {
4090
+ /**
4091
+ * No such run, or you do not own it.
4092
+ */
4093
+ 404: ResponseError;
4094
+ /**
4095
+ * The run was started without a stream, so there is nothing to revoke.
4096
+ */
4097
+ 409: ResponseError;
4098
+ };
4099
+
4100
+ export type RevokeLiveStreamError =
4101
+ RevokeLiveStreamErrors[keyof RevokeLiveStreamErrors];
4102
+
4103
+ export type RevokeLiveStreamResponses = {
4104
+ /**
4105
+ * Revoked (or already revoked).
4106
+ */
4107
+ 200: LiveStreamRevoked;
4108
+ };
4109
+
4110
+ export type RevokeLiveStreamResponse =
4111
+ RevokeLiveStreamResponses[keyof RevokeLiveStreamResponses];
4112
+
4113
+ export type RotateLiveStreamData = {
4114
+ body?: never;
4115
+ path: {
4116
+ runId: string;
4117
+ };
4118
+ query?: never;
4119
+ url: "/live/{runId}/stream";
4120
+ };
4121
+
4122
+ export type RotateLiveStreamErrors = {
4123
+ /**
4124
+ * No such run, or you do not own it.
4125
+ */
4126
+ 404: ResponseError;
4127
+ /**
4128
+ * One of three reasons, each its own message: the run was started without a stream; its stream was
4129
+ * revoked (a revoked stream cannot be restored: start the run again with a stream); or the run is stopped.
4130
+ *
4131
+ */
4132
+ 409: ResponseError;
4133
+ /**
4134
+ * Your plan does not let you broadcast a run's signals. The message names your plan; retrying will not help until it changes, so there is no `Retry-After`.
4135
+ */
4136
+ 429: ResponseError;
4137
+ };
4138
+
4139
+ export type RotateLiveStreamError =
4140
+ RotateLiveStreamErrors[keyof RotateLiveStreamErrors];
4141
+
4142
+ export type RotateLiveStreamResponses = {
4143
+ /**
4144
+ * The new URL.
4145
+ */
4146
+ 200: LiveStreamUrl;
4147
+ };
4148
+
4149
+ export type RotateLiveStreamResponse =
4150
+ RotateLiveStreamResponses[keyof RotateLiveStreamResponses];
4151
+
3943
4152
  export type GetLiveRunSignalsData = {
3944
4153
  body?: never;
3945
4154
  path: {