@mfxhub/sdk 0.1.2 → 0.2.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/CHANGELOG.md +40 -1
- package/README.md +8 -0
- package/dist/accounts.d.ts +47 -0
- package/dist/accounts.js +79 -0
- package/dist/catalog.d.ts +13 -0
- package/dist/catalog.js +14 -0
- package/dist/client.d.ts +5 -1
- package/dist/client.js +14 -1
- package/dist/events.d.ts +13 -0
- package/dist/events.js +5 -0
- package/dist/execution.d.ts +84 -0
- package/dist/execution.js +129 -1
- package/dist/generated/api.d.ts +1104 -66
- package/dist/index.d.ts +8 -6
- package/dist/index.js +3 -3
- package/dist/stream.js +5 -1
- package/dist/terminals.d.ts +32 -4
- package/dist/terminals.js +60 -4
- package/dist/version.d.ts +4 -0
- package/dist/version.js +5 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -11,16 +11,18 @@ export type { Answer, Budget, ClientOptions, RequestSpec } from "./client.js";
|
|
|
11
11
|
export * from "./errors.js";
|
|
12
12
|
export { Page } from "./pages.js";
|
|
13
13
|
export { Catalog } from "./catalog.js";
|
|
14
|
-
export type { Quote, QuoteOptions } from "./catalog.js";
|
|
15
|
-
export {
|
|
14
|
+
export type { BrokerCatalogue, CatalogSymbol, Quote, QuoteOptions, SymbolPage } from "./catalog.js";
|
|
15
|
+
export type { MaintenanceWindowChanged, SymbolSpecChange, SymbolSpecChanged, TerminalConditionChanged, } from "./events.js";
|
|
16
|
+
export { Accounts } from "./accounts.js";
|
|
17
|
+
export type { Account, Deal, DealPageOptions, DealWindow, PendingOrder, PendingOrderList, Position, PositionList, } from "./accounts.js";
|
|
18
|
+
export { Execution, POLL_CAP_MS, POLL_FROM_MS } from "./execution.js";
|
|
16
19
|
export { CLOSE_LIFETIME, CLOSE_REAUTHENTICATE, CLOSE_SLOW_CONSUMER, Channel, ChannelRefused, MfxStream, Resync, StreamClosed, StreamMessage, wsConnector, } from "./stream.js";
|
|
17
20
|
export type { Connector, StreamConnection, StreamEvent, StreamOptions, StreamStats, Timeframe, } from "./stream.js";
|
|
18
|
-
export type { OrderType, PlaceOrder, Side } from "./execution.js";
|
|
21
|
+
export type { ClosePosition, ClosePositionBy, ClosePositionPartial, Keyed, ModifyOrder, ModifyPosition, OrderType, PlaceOrder, SetTrailingStop, Side, WaitFor, } from "./execution.js";
|
|
19
22
|
export type { CommandState, ExecutionResult, Reason, Tickets } from "./results.js";
|
|
20
23
|
export { Terminals, isUsable } from "./terminals.js";
|
|
21
|
-
export type { CreateTerminal, PageOptions, Redundancy, Terminal, TerminalState, } from "./terminals.js";
|
|
24
|
+
export type { CreateTerminal, JournalLine, JournalOptions, PageOptions, Redundancy, Terminal, TerminalFilter, TerminalJournal, TerminalState, } from "./terminals.js";
|
|
22
25
|
export { RequestSigner, SigningKey, signingMessage } from "./signing.js";
|
|
23
26
|
export { KEY_HEADER, NONCE_HEADER, SIGNATURE_HEADER, TIMESTAMP_HEADER } from "./signing.js";
|
|
24
27
|
export type { components, operations, paths } from "./generated/api.js";
|
|
25
|
-
|
|
26
|
-
export declare const VERSION = "0.1.2";
|
|
28
|
+
export { VERSION } from "./version.js";
|
package/dist/index.js
CHANGED
|
@@ -10,10 +10,10 @@ export { MfxClient, DEFAULT_READ_RETRIES, DEFAULT_TIMEOUT_MS } from "./client.js
|
|
|
10
10
|
export * from "./errors.js";
|
|
11
11
|
export { Page } from "./pages.js";
|
|
12
12
|
export { Catalog } from "./catalog.js";
|
|
13
|
-
export {
|
|
13
|
+
export { Accounts } from "./accounts.js";
|
|
14
|
+
export { Execution, POLL_CAP_MS, POLL_FROM_MS } from "./execution.js";
|
|
14
15
|
export { CLOSE_LIFETIME, CLOSE_REAUTHENTICATE, CLOSE_SLOW_CONSUMER, Channel, ChannelRefused, MfxStream, Resync, StreamClosed, StreamMessage, wsConnector, } from "./stream.js";
|
|
15
16
|
export { Terminals, isUsable } from "./terminals.js";
|
|
16
17
|
export { RequestSigner, SigningKey, signingMessage } from "./signing.js";
|
|
17
18
|
export { KEY_HEADER, NONCE_HEADER, SIGNATURE_HEADER, TIMESTAMP_HEADER } from "./signing.js";
|
|
18
|
-
|
|
19
|
-
export const VERSION = "0.1.2";
|
|
19
|
+
export { VERSION } from "./version.js";
|
package/dist/stream.js
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
// The upgrade is signed exactly as a REST request is, over `GET /v1/stream`.
|
|
24
24
|
import WebSocket from "ws";
|
|
25
25
|
import { AuthError, MfxError, MfxTransportError, errorFor } from "./errors.js";
|
|
26
|
+
import { USER_AGENT } from "./version.js";
|
|
26
27
|
/** The server says why it hung up. 4001 is the one reconnecting cannot fix. */
|
|
27
28
|
export const CLOSE_REAUTHENTICATE = 4001;
|
|
28
29
|
export const CLOSE_SLOW_CONSUMER = 4008;
|
|
@@ -225,7 +226,10 @@ export class MfxStream {
|
|
|
225
226
|
/** Opens the connection. {@link MfxClient.stream} does this for you. */
|
|
226
227
|
async open() {
|
|
227
228
|
const path = new URL(this.#url).pathname;
|
|
228
|
-
this.#connection = await this.#connect(this.#url,
|
|
229
|
+
this.#connection = await this.#connect(this.#url, {
|
|
230
|
+
...this.#client.signer.headersFor("GET", path),
|
|
231
|
+
"User-Agent": USER_AGENT,
|
|
232
|
+
});
|
|
229
233
|
return this;
|
|
230
234
|
}
|
|
231
235
|
/** Subscribe to one channel. Subscribing twice is not an error. */
|
package/dist/terminals.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MfxClient } from "./client.js";
|
|
2
|
-
import type { components } from "./generated/api.js";
|
|
2
|
+
import type { components, operations } from "./generated/api.js";
|
|
3
3
|
import { type Page } from "./pages.js";
|
|
4
4
|
/** A terminal, as the API describes it. */
|
|
5
5
|
export type Terminal = components["schemas"]["TenantTerminal"];
|
|
@@ -7,6 +7,24 @@ export type Terminal = components["schemas"]["TenantTerminal"];
|
|
|
7
7
|
export type TerminalState = Terminal["state"];
|
|
8
8
|
/** How a terminal is replicated. */
|
|
9
9
|
export type Redundancy = components["schemas"]["TerminalCreate"]["redundancy"];
|
|
10
|
+
/** The states the list can be narrowed to, as the contract declares them. */
|
|
11
|
+
type ListState = NonNullable<NonNullable<operations["listTerminals"]["parameters"]["query"]>["state"]>;
|
|
12
|
+
/** A terminal's journal: its lines newest first, and whether they were read live. */
|
|
13
|
+
export type TerminalJournal = components["schemas"]["TerminalJournal"];
|
|
14
|
+
/** One line of a terminal's MetaTrader journal. */
|
|
15
|
+
export type JournalLine = components["schemas"]["JournalLine"];
|
|
16
|
+
/** What {@link Terminals.journal} takes. */
|
|
17
|
+
export interface JournalOptions {
|
|
18
|
+
/** How many lines, newest first: 1 to 200. The platform's default is 100. */
|
|
19
|
+
readonly lines?: number;
|
|
20
|
+
}
|
|
21
|
+
/** Narrow a terminal list in the query, before the page is cut. */
|
|
22
|
+
export interface TerminalFilter {
|
|
23
|
+
/** Only terminals carrying every one of these labels, by exact key and value. At most 10. */
|
|
24
|
+
readonly labels?: Readonly<Record<string, string>>;
|
|
25
|
+
/** Only terminals in one of these states. */
|
|
26
|
+
readonly state?: ListState | ListState[number];
|
|
27
|
+
}
|
|
10
28
|
/** What {@link Terminals.create} takes. */
|
|
11
29
|
export interface CreateTerminal {
|
|
12
30
|
/** The broker, from the catalogue. */
|
|
@@ -25,7 +43,7 @@ export interface CreateTerminal {
|
|
|
25
43
|
readonly redundancy?: Redundancy;
|
|
26
44
|
}
|
|
27
45
|
/** What {@link Terminals.page} takes. */
|
|
28
|
-
export interface PageOptions {
|
|
46
|
+
export interface PageOptions extends TerminalFilter {
|
|
29
47
|
/** The `nextCursor` of the page before; leave it out for the first page. */
|
|
30
48
|
readonly cursor?: string;
|
|
31
49
|
/** How many to a page, 1 to 200. */
|
|
@@ -45,11 +63,21 @@ export declare class Terminals {
|
|
|
45
63
|
get(terminalId: string): Promise<Terminal>;
|
|
46
64
|
/** One page of this tenant's terminals, newest first. One request. */
|
|
47
65
|
page(options?: PageOptions): Promise<Page<Terminal>>;
|
|
48
|
-
/**
|
|
49
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Every terminal, following the cursor, one request a page. There is no total. `labels` and
|
|
68
|
+
* `state` narrow the list on the platform, so a filtered page is never short for being filtered.
|
|
69
|
+
*/
|
|
70
|
+
list(options?: Omit<PageOptions, "cursor">): AsyncGenerator<Terminal, void, undefined>;
|
|
71
|
+
/**
|
|
72
|
+
* The terminal's MetaTrader journal, newest first. While it runs the lines are read from its
|
|
73
|
+
* cell (`from: "live"`); after it stops they are the last lines its cell kept, for 24 hours
|
|
74
|
+
* (`from: "last_words"`). Account numbers are masked. A terminal with no lines held is 409.
|
|
75
|
+
*/
|
|
76
|
+
journal(terminalId: string, options?: JournalOptions): Promise<TerminalJournal>;
|
|
50
77
|
/**
|
|
51
78
|
* Ask for a terminal. Answered at once in state REQUESTED; the move to a cell happens after.
|
|
52
79
|
* Sent once and never retried: if the answer is lost, send the same idempotency key again.
|
|
53
80
|
*/
|
|
54
81
|
create(request: CreateTerminal): Promise<Terminal>;
|
|
55
82
|
}
|
|
83
|
+
export {};
|
package/dist/terminals.js
CHANGED
|
@@ -10,6 +10,32 @@
|
|
|
10
10
|
// exception, because it is the SDK's own type, not the API's.
|
|
11
11
|
import { idempotencyKey, limit as pageLimit, uuid } from "./arguments.js";
|
|
12
12
|
import { everyItem, pageOf } from "./pages.js";
|
|
13
|
+
function labelQuery(labels) {
|
|
14
|
+
if (labels === undefined)
|
|
15
|
+
return undefined;
|
|
16
|
+
const pairs = Object.entries(labels);
|
|
17
|
+
if (pairs.length > 10)
|
|
18
|
+
throw new RangeError("labels is at most 10 pairs");
|
|
19
|
+
return pairs.map(([key, value]) => {
|
|
20
|
+
if (key === "" || key.includes(":")) {
|
|
21
|
+
throw new RangeError(`a label key is not empty and has no colon: ${JSON.stringify(key)}`);
|
|
22
|
+
}
|
|
23
|
+
if (typeof value !== "string")
|
|
24
|
+
throw new TypeError(`label ${key} is a string`);
|
|
25
|
+
if (key.length + 1 + value.length > 200) {
|
|
26
|
+
throw new RangeError(`label ${key} is over 200 characters`);
|
|
27
|
+
}
|
|
28
|
+
return `${key}:${value}`;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function stateQuery(state) {
|
|
32
|
+
if (state === undefined)
|
|
33
|
+
return undefined;
|
|
34
|
+
const states = typeof state === "string" ? [state] : state;
|
|
35
|
+
if (states.length === 0)
|
|
36
|
+
throw new RangeError("state is one or more states; got none");
|
|
37
|
+
return states.join(",");
|
|
38
|
+
}
|
|
13
39
|
/**
|
|
14
40
|
* Can this terminal be used right now: market data, execution, account reads? True only in ACTIVE.
|
|
15
41
|
* OFFLINE means its cell is not reporting; the platform brings it back by itself, so retry rather
|
|
@@ -38,16 +64,46 @@ export class Terminals {
|
|
|
38
64
|
const body = await this.#client.read({
|
|
39
65
|
method: "GET",
|
|
40
66
|
path: "/terminals",
|
|
41
|
-
query: {
|
|
67
|
+
query: {
|
|
68
|
+
cursor: options.cursor,
|
|
69
|
+
limit,
|
|
70
|
+
label: labelQuery(options.labels),
|
|
71
|
+
state: stateQuery(options.state),
|
|
72
|
+
},
|
|
42
73
|
});
|
|
43
74
|
return pageOf(body);
|
|
44
75
|
}
|
|
45
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* Every terminal, following the cursor, one request a page. There is no total. `labels` and
|
|
78
|
+
* `state` narrow the list on the platform, so a filtered page is never short for being filtered.
|
|
79
|
+
*/
|
|
46
80
|
list(options = {}) {
|
|
47
81
|
const limit = pageLimit(options.limit);
|
|
48
|
-
|
|
49
|
-
...(cursor === undefined ? {} : { cursor }),
|
|
82
|
+
const rest = {
|
|
50
83
|
...(limit === undefined ? {} : { limit }),
|
|
84
|
+
...(options.labels === undefined ? {} : { labels: options.labels }),
|
|
85
|
+
...(options.state === undefined ? {} : { state: options.state }),
|
|
86
|
+
};
|
|
87
|
+
return everyItem((cursor) => this.page({ ...rest, ...(cursor === undefined ? {} : { cursor }) }));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The terminal's MetaTrader journal, newest first. While it runs the lines are read from its
|
|
91
|
+
* cell (`from: "live"`); after it stops they are the last lines its cell kept, for 24 hours
|
|
92
|
+
* (`from: "last_words"`). Account numbers are masked. A terminal with no lines held is 409.
|
|
93
|
+
*/
|
|
94
|
+
async journal(terminalId, options = {}) {
|
|
95
|
+
const id = uuid("terminalId", terminalId);
|
|
96
|
+
const lines = options.lines;
|
|
97
|
+
if (lines !== undefined && (typeof lines !== "number" || !Number.isInteger(lines))) {
|
|
98
|
+
throw new TypeError("lines is a whole number");
|
|
99
|
+
}
|
|
100
|
+
if (lines !== undefined && (lines < 1 || lines > 200)) {
|
|
101
|
+
throw new RangeError(`lines is 1 to 200; got ${lines}`);
|
|
102
|
+
}
|
|
103
|
+
return (await this.#client.read({
|
|
104
|
+
method: "GET",
|
|
105
|
+
path: `/terminals/${id}/journal`,
|
|
106
|
+
query: { lines },
|
|
51
107
|
}));
|
|
52
108
|
}
|
|
53
109
|
/**
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// This package's version, in one place: exported by the package, and named by every request.
|
|
2
|
+
/** This package's version. */
|
|
3
|
+
export const VERSION = "0.2.1";
|
|
4
|
+
/** What every request says it is, as a product token: the SDK's language and its version. */
|
|
5
|
+
export const USER_AGENT = `mfx-sdk-typescript/${VERSION}`;
|
package/package.json
CHANGED