@flexemarkets/fm-sdk 0.0.11 → 0.1.1
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/client.d.ts +213 -15
- package/dist/client.js +486 -62
- package/dist/client.js.map +1 -1
- package/dist/hal.d.ts +15 -0
- package/dist/hal.js +14 -0
- package/dist/hal.js.map +1 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.js +3 -8
- package/dist/index.js.map +1 -1
- package/dist/market-view.d.ts +9 -7
- package/dist/market-view.js +25 -18
- package/dist/market-view.js.map +1 -1
- package/dist/order-utils.d.ts +4 -4
- package/dist/order-utils.js +10 -6
- package/dist/order-utils.js.map +1 -1
- package/dist/stomp.d.ts +32 -5
- package/dist/stomp.js +37 -16
- package/dist/stomp.js.map +1 -1
- package/dist/ticker.js +3 -3
- package/dist/ticker.js.map +1 -1
- package/dist/timestamps.d.ts +30 -0
- package/dist/timestamps.js +39 -0
- package/dist/timestamps.js.map +1 -0
- package/dist/types.d.ts +144 -22
- package/dist/types.js +93 -14
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Port of fm.client (Python) / fm.Flexemarkets (Java).
|
|
5
5
|
*/
|
|
6
|
-
import type { Account, Allotment, ClientConnection, Holding, Market, Marketplace, Order, Person, Session } from "./types.js";
|
|
6
|
+
import type { Account, Allotment, ClientConnection, Holding, ManagerOtpBundle, Market, Marketplace, Order, Person, Security, Session, TickGrid, Token } from "./types.js";
|
|
7
7
|
import { EventListener, type EventCallback } from "./stomp.js";
|
|
8
|
-
import {
|
|
8
|
+
import type { ApiRoot } from "./hal.js";
|
|
9
|
+
import { type MarketView, type Subscription } from "./market-view.js";
|
|
9
10
|
import type { Snapshot } from "./snapshot.js";
|
|
10
11
|
export declare class FlexemarketsError extends Error {
|
|
11
12
|
}
|
|
@@ -19,9 +20,91 @@ export declare class ConnectionFailedError extends FlexemarketsError {
|
|
|
19
20
|
}
|
|
20
21
|
export declare class ConfigurationError extends FlexemarketsError {
|
|
21
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* A response the SDK has no better name for, carrying its status and body.
|
|
25
|
+
*
|
|
26
|
+
* The fallback. A status with a meaning worth acting on gets its own type —
|
|
27
|
+
* {@link AuthenticationError}, {@link ConflictError} — and this is what is
|
|
28
|
+
* left, so a caller can read the status rather than parse a message.
|
|
29
|
+
*/
|
|
30
|
+
export declare class HttpError extends FlexemarketsError {
|
|
31
|
+
readonly statusCode: number;
|
|
32
|
+
readonly body: string;
|
|
33
|
+
constructor(statusCode: number, body: string);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The call could not be completed: the transport failed, or the response was
|
|
37
|
+
* not something the SDK could read.
|
|
38
|
+
*
|
|
39
|
+
* Distinct from {@link HttpError}, which means the server answered and the
|
|
40
|
+
* answer was an error. This means there was no usable answer at all — a
|
|
41
|
+
* malformed body, or a link the API root does not carry.
|
|
42
|
+
*/
|
|
43
|
+
export declare class ApiError extends FlexemarketsError {
|
|
44
|
+
}
|
|
45
|
+
/** A 409. The Java and Python SDKs have raised this since the admin surface landed. */
|
|
46
|
+
export declare class ConflictError extends FlexemarketsError {
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* An account name was taken, and the server proposed another.
|
|
50
|
+
*
|
|
51
|
+
* A subclass of {@link ConflictError} rather than a sibling, so a caller that
|
|
52
|
+
* handles conflicts generally still catches this one. The suggestion is worth
|
|
53
|
+
* surfacing rather than retrying blindly: it is the name the account would end
|
|
54
|
+
* up known by.
|
|
55
|
+
*/
|
|
56
|
+
export declare class AccountNameConflictError extends ConflictError {
|
|
57
|
+
readonly requestedName: string;
|
|
58
|
+
readonly suggestedName: string | null;
|
|
59
|
+
constructor(message: string, requestedName: string, suggestedName: string | null);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A user could not be deleted because they still own marketplace data —
|
|
63
|
+
* orders or allotments. Deleting them would orphan it, so the server refuses;
|
|
64
|
+
* the caller has to decide what happens to the data first.
|
|
65
|
+
*/
|
|
66
|
+
export declare class PersonHasMarketplaceDataError extends ConflictError {
|
|
67
|
+
readonly userId: number;
|
|
68
|
+
constructor(message: string, userId: number);
|
|
69
|
+
}
|
|
22
70
|
type JsonObject = Record<string, unknown>;
|
|
71
|
+
export declare function parsePerson(data: JsonObject | null | undefined): Person | null;
|
|
72
|
+
export declare function parseAccount(data: JsonObject | null | undefined): Account | null;
|
|
73
|
+
export declare function parseToken(data: JsonObject): Token;
|
|
74
|
+
export declare function parseSecurity(data: JsonObject): Security;
|
|
75
|
+
export declare function parseMarket(data: JsonObject): Market;
|
|
76
|
+
export declare function parseMarketplace(data: JsonObject): Marketplace;
|
|
77
|
+
export declare function parseSession(data: JsonObject): Session;
|
|
23
78
|
export declare function parseOrder(data: JsonObject): Order;
|
|
24
79
|
export declare function parseHolding(data: JsonObject): Holding;
|
|
80
|
+
export declare function parseConnection(data: JsonObject): ClientConnection;
|
|
81
|
+
/**
|
|
82
|
+
* The most aggressive price this market will accept on `side`.
|
|
83
|
+
*
|
|
84
|
+
* Ticks are anchored at `priceMinimum`, not at zero — the server tests
|
|
85
|
+
* `(price - priceMinimum) % priceTick` — so the top of the range is only legal
|
|
86
|
+
* when the range is a whole number of ticks. The highest legal price is the
|
|
87
|
+
* last tick at or below `priceMaximum`. A tick of zero marks a fixed dimension,
|
|
88
|
+
* where the two bounds are equal and there is one legal price.
|
|
89
|
+
*/
|
|
90
|
+
export declare function marketableLimit(market: Market, side: string): number;
|
|
91
|
+
/**
|
|
92
|
+
* Point the API root's links back at the host that was dialled.
|
|
93
|
+
*
|
|
94
|
+
* The server builds these hrefs from the request it believes it received, and
|
|
95
|
+
* behind a proxy that belief can be wrong: an origin reached over a plaintext
|
|
96
|
+
* leg reports `http://` even though the caller arrived on `https://`. Every
|
|
97
|
+
* call that goes through a link — which is most of them — then leaves on plain
|
|
98
|
+
* HTTP and meets the edge's redirect. A GET survives it. A POST does not: a
|
|
99
|
+
* 301 is followed as a GET with the body dropped, so placing an order or
|
|
100
|
+
* opening a session fails with nothing placed and nothing pointing at the
|
|
101
|
+
* scheme.
|
|
102
|
+
*
|
|
103
|
+
* Only the origin is replaced. The path, query and any URI template are the
|
|
104
|
+
* server's to choose; where it is reachable is not, and the token in hand was
|
|
105
|
+
* issued by the origin dialled, not by whatever the links name.
|
|
106
|
+
*/
|
|
107
|
+
export declare function rebaseApiRoot(root: ApiRoot, endpoint: string): ApiRoot;
|
|
25
108
|
/**
|
|
26
109
|
* Resolve an `--endpoint` value to config overrides. A bare marketplace id
|
|
27
110
|
* (e.g. "2540") resolves to that marketplace on the default production host; a
|
|
@@ -29,11 +112,6 @@ export declare function parseHolding(data: JsonObject): Holding;
|
|
|
29
112
|
* URL. Development environments give a full URL when localhost is wanted.
|
|
30
113
|
*/
|
|
31
114
|
export declare function resolveEndpoint(endpoint: string): Record<string, string>;
|
|
32
|
-
export interface FlexemarketsOptions {
|
|
33
|
-
credential?: string;
|
|
34
|
-
endpoint?: string;
|
|
35
|
-
clientDescription?: string;
|
|
36
|
-
}
|
|
37
115
|
export declare class Flexemarkets {
|
|
38
116
|
private readonly _clientDescription;
|
|
39
117
|
private readonly _endpoint;
|
|
@@ -42,6 +120,7 @@ export declare class Flexemarkets {
|
|
|
42
120
|
private _apiRoot;
|
|
43
121
|
private _account;
|
|
44
122
|
private _user;
|
|
123
|
+
private _tokenObj;
|
|
45
124
|
private _eventListener;
|
|
46
125
|
private constructor();
|
|
47
126
|
/** Connect to the Flexemarkets API. */
|
|
@@ -74,29 +153,125 @@ export declare class Flexemarkets {
|
|
|
74
153
|
*/
|
|
75
154
|
private _getText;
|
|
76
155
|
private _post;
|
|
156
|
+
/**
|
|
157
|
+
* Register a new account and its owner, returning the owner's token.
|
|
158
|
+
*
|
|
159
|
+
* The owner's credentials go out as `ownerEmail`/`ownerPassword`. Sending
|
|
160
|
+
* `email`/`password` instead creates an account with an owner the server
|
|
161
|
+
* cannot sign in as.
|
|
162
|
+
*/
|
|
163
|
+
signup(accountName: string, email: string, password: string, firstName?: string | null, lastName?: string | null): Promise<Token>;
|
|
164
|
+
/** Approve an account by name, returning it as it now stands. */
|
|
165
|
+
approveAccount(accountName: string): Promise<Account | null>;
|
|
166
|
+
/** One account by id. */
|
|
167
|
+
accountById(accountId: number): Promise<Account | null>;
|
|
168
|
+
/** One user by id. */
|
|
169
|
+
userById(userId: number): Promise<Person>;
|
|
170
|
+
/** The marketplace's private-trader identifiers. */
|
|
171
|
+
identifiers(marketplaceId: number): Promise<string[]>;
|
|
172
|
+
/** Delete the caller's own account. Its own route, not accounts/{yourId}. */
|
|
173
|
+
deleteMyAccount(): Promise<void>;
|
|
174
|
+
/** Every account on the server. Admin-only. */
|
|
175
|
+
accounts(): Promise<Account[]>;
|
|
176
|
+
/** Delete an account. Destructive, and takes its users with it. */
|
|
177
|
+
deleteAccount(accountId: number): Promise<void>;
|
|
178
|
+
/** Create a user in the caller's account. */
|
|
179
|
+
createUser(email: string, password: string, firstName: string, lastName: string, roles?: string[]): Promise<Person>;
|
|
180
|
+
/** Delete a user. Destructive. */
|
|
181
|
+
deleteUser(userId: number): Promise<void>;
|
|
182
|
+
/** Create an empty marketplace. See also {@link createMarketplaceFromJson}. */
|
|
183
|
+
/** Delete a marketplace, and with it its sessions and their history. */
|
|
184
|
+
deleteMarketplace(marketplaceId: number): Promise<void>;
|
|
185
|
+
/**
|
|
186
|
+
* Add a market to a marketplace.
|
|
187
|
+
*
|
|
188
|
+
* Both dimensions are the caller's. Unit bounds used to be fixed at 1/100/1
|
|
189
|
+
* with no way to say otherwise, on a call that set the price grid three
|
|
190
|
+
* arguments earlier — and the server enforces the two identically, refusing
|
|
191
|
+
* an order for "units is not on a tic" exactly as for a price. Omitting
|
|
192
|
+
* `units` keeps the old default.
|
|
193
|
+
*/
|
|
194
|
+
createMarket(marketplaceId: number, symbol: string, name: string, price: TickGrid, units?: TickGrid, privateMarket?: boolean): Promise<Market>;
|
|
195
|
+
/**
|
|
196
|
+
* Mint one-time passcodes for the given users.
|
|
197
|
+
*
|
|
198
|
+
* These are credentials: not to be logged, not to be persisted, and
|
|
199
|
+
* delivered to the person they belong to.
|
|
200
|
+
*/
|
|
201
|
+
managerOtpBundle(userIds: number[]): Promise<ManagerOtpBundle>;
|
|
202
|
+
/** DELETE, whose answer is a status and nothing worth parsing. */
|
|
203
|
+
private _delete;
|
|
77
204
|
private _fetchApiRoot;
|
|
78
205
|
marketplaces(): Promise<Marketplace[]>;
|
|
79
206
|
marketplace(marketplaceId: number): Promise<Marketplace>;
|
|
80
207
|
markets(marketplaceId: number): Promise<Market[]>;
|
|
208
|
+
/**
|
|
209
|
+
* The token this connection signed in with.
|
|
210
|
+
*
|
|
211
|
+
* Exposed so a caller can open a sibling connection on the same identity
|
|
212
|
+
* without holding the password again.
|
|
213
|
+
*/
|
|
214
|
+
token(): Token;
|
|
215
|
+
/** Whether this connection's user holds ROLE_ADMIN. */
|
|
216
|
+
isAdmin(): boolean;
|
|
217
|
+
/**
|
|
218
|
+
* Whether this connection's user holds ROLE_MANAGER — the role that runs a
|
|
219
|
+
* study: opening and closing sessions, staging allocations, minting
|
|
220
|
+
* passcodes. Python has had it since the management surface landed.
|
|
221
|
+
*/
|
|
222
|
+
isManager(): boolean;
|
|
223
|
+
hasRole(role: string): boolean;
|
|
81
224
|
symbols(marketplaceId: number): Promise<string[]>;
|
|
82
|
-
|
|
225
|
+
/**
|
|
226
|
+
* The marketplace's sessions — all of them.
|
|
227
|
+
*
|
|
228
|
+
* There is no server-side filter. The route takes no session argument, so
|
|
229
|
+
* the `sessionIds` this used to accept was silently ignored: it returned the
|
|
230
|
+
* whole history and looked like it had filtered. Filter the result; fm-ui
|
|
231
|
+
* already does.
|
|
232
|
+
*
|
|
233
|
+
* On `GET /api/v1/marketplaces/{id}/sessions`, which answers with the same
|
|
234
|
+
* fields as the V0 route it replaces — verified against a running server,
|
|
235
|
+
* not assumed — and needs no `format=application/json` to avoid HAL.
|
|
236
|
+
*/
|
|
237
|
+
sessions(marketplaceId: number): Promise<Session[]>;
|
|
83
238
|
session(marketplaceId: number): Promise<Session>;
|
|
84
239
|
submitLimit(marketplaceId: number, marketId: number, side: string, units: number, price: number): Promise<Order>;
|
|
240
|
+
/**
|
|
241
|
+
* Cross the book: buy at the highest price this market allows, sell at the
|
|
242
|
+
* lowest. Immediate or cancel — whatever does not fill is cancelled.
|
|
243
|
+
*
|
|
244
|
+
* There is no market order on the server. Its type switch falls through to
|
|
245
|
+
* `LIMIT`, so every submission is bounds-checked against the market and must
|
|
246
|
+
* sit on a tick — which is why this asks the marketplace for the market
|
|
247
|
+
* first, and costs a round trip {@link submitLimit} does not.
|
|
248
|
+
*
|
|
249
|
+
* The cancel is unconditional: the exchange consumes a cancel by itself when
|
|
250
|
+
* no units remain, so a complete fill costs a harmless round trip rather than
|
|
251
|
+
* an inspection that would race the book. Without it, a market order that did
|
|
252
|
+
* not fill would rest at the market's extreme — the best price in the book,
|
|
253
|
+
* standing, for anyone to take.
|
|
254
|
+
*
|
|
255
|
+
* Returns the limit order as submitted. What it filled is a property of the
|
|
256
|
+
* book afterwards, not of this value.
|
|
257
|
+
*/
|
|
258
|
+
submitMarket(marketplaceId: number, marketId: number, side: string, units: number): Promise<Order>;
|
|
259
|
+
private _market;
|
|
85
260
|
submitCancel(marketplaceId: number, marketId: number, originalId: number): Promise<Order>;
|
|
86
261
|
/**
|
|
87
|
-
*
|
|
262
|
+
* The active-orders snapshot: every resting limit order on the
|
|
88
263
|
* marketplace's current session, plus the `x-fm-as-of-seq` sequence
|
|
89
|
-
* the snapshot was read at. Used by `MarketView`
|
|
264
|
+
* the snapshot was read at. Used by `MarketView` seeding
|
|
90
265
|
* — clients apply WS deltas whose seq is greater than the returned
|
|
91
266
|
* value and skip those whose seq is less than or equal.
|
|
92
267
|
*/
|
|
93
|
-
|
|
268
|
+
activeOrders(marketplaceId: number): Promise<Snapshot<Order[]>>;
|
|
94
269
|
/**
|
|
95
|
-
*
|
|
96
|
-
* Same `x-fm-as-of-seq` contract as `
|
|
270
|
+
* The recent-trades snapshot, for seeding the trade-history tape.
|
|
271
|
+
* Same `x-fm-as-of-seq` contract as `activeOrders`. Server caps
|
|
97
272
|
* at 5000; default size is 1000.
|
|
98
273
|
*/
|
|
99
|
-
|
|
274
|
+
recentTrades(marketplaceId: number, size?: number): Promise<Snapshot<Order[]>>;
|
|
100
275
|
orders(marketplaceId: number, options?: {
|
|
101
276
|
symbol?: string;
|
|
102
277
|
sessionIds?: number[];
|
|
@@ -104,7 +279,14 @@ export declare class Flexemarkets {
|
|
|
104
279
|
trades(marketplaceId: number, symbol: string): Promise<Order[]>;
|
|
105
280
|
holdings(marketplaceId: number, sessionIds?: number[] | null): Promise<Holding[]>;
|
|
106
281
|
holding(marketplaceId: number): Promise<Holding>;
|
|
107
|
-
|
|
282
|
+
/**
|
|
283
|
+
* Who is attached to the marketplace — all of them.
|
|
284
|
+
*
|
|
285
|
+
* No server-side filter, for the reason {@link sessions} gives. A connection
|
|
286
|
+
* carries the session it belonged to, so "who was present in that run" is a
|
|
287
|
+
* filter on the result.
|
|
288
|
+
*/
|
|
289
|
+
connections(marketplaceId: number): Promise<ClientConnection[]>;
|
|
108
290
|
/**
|
|
109
291
|
* Create a marketplace from its JSON definition, returning what was made.
|
|
110
292
|
*
|
|
@@ -168,6 +350,22 @@ export declare class Flexemarkets {
|
|
|
168
350
|
_releaseSharedView(marketplaceId: number): void;
|
|
169
351
|
/** Start receiving real-time events via WebSocket STOMP. */
|
|
170
352
|
listen(marketplaceId: number, callback: EventCallback): Promise<void>;
|
|
353
|
+
/**
|
|
354
|
+
* Open an *independent* event subscription, delivering to `callback` until
|
|
355
|
+
* the returned unsubscribe function is invoked.
|
|
356
|
+
*
|
|
357
|
+
* Unlike {@link listen}, which is one per connection and replaces itself,
|
|
358
|
+
* several of these coexist: each has its own stream and its own lifetime.
|
|
359
|
+
* That is what lets more than one MarketView live in one connection without
|
|
360
|
+
* trampling each other — the mechanism was already here for exactly that, as
|
|
361
|
+
* the package-private `_connectEvents`, but a caller who wanted a second
|
|
362
|
+
* stream of their own had no way to ask for one.
|
|
363
|
+
*
|
|
364
|
+
* Returns an unsubscribe function rather than an object with `close()`,
|
|
365
|
+
* matching what MarketView's `on*` handlers already return here. Java
|
|
366
|
+
* returns a `Subscription`; both names describe the same lifetime.
|
|
367
|
+
*/
|
|
368
|
+
subscribe(marketplaceId: number, callback: EventCallback): Promise<Subscription>;
|
|
171
369
|
/**
|
|
172
370
|
* Package-private helper used by {@link DefaultMarketView} (Phase 2d)
|
|
173
371
|
* to own its own EventListener subscription rather than clobbering
|