@0xmonaco/react 1.0.50 → 1.0.53

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.
@@ -1,11 +1,138 @@
1
+ import type { Order, OrderEvent, OrderSnapshotItem, OrderStatus } from "@0xmonaco/types";
1
2
  import type { UseUserOrdersReturn } from "./types";
3
+ export declare function useUserOrders(maxOrders?: number): UseUserOrdersReturn;
2
4
  /**
3
- * Hook for subscribing to real-time user order events via WebSocket (authenticated)
5
+ * Map one `orders` snapshot row onto the REST `Order` model, or `null` when
6
+ * this SDK version cannot describe it.
4
7
  *
5
- * Fetches initial orders from the REST API, then subscribes to real-time updates.
6
- * Requires authentication - the user must be logged in with a session key.
7
- * User is identified on the backend from the signed session-key handshake.
8
+ * Same decline contract as {@link orderFromEvent}, for the same reason: the
9
+ * wire values are handed through unvalidated, and relabelling a future order
10
+ * type or side renders an order as something it is not. `status` joins the
11
+ * declining set here, unlike on an `OrderPlaced` — that event IS a submitted
12
+ * order whatever string it carries, whereas a snapshot row's status is the
13
+ * order's actual resting state and has no honest substitute.
8
14
  *
9
- * @param maxOrders - Maximum number of orders to keep in state (default: 50)
15
+ * The row's optionals arrive as explicit `null` (Rust `Option`s serialized
16
+ * without `skip_serializing_if`), so they are normalized to absent: the REST
17
+ * model declares them `?:`, and leaking `null` past it would have consumers
18
+ * branching on a value the model says cannot occur.
10
19
  */
11
- export declare function useUserOrders(maxOrders?: number): UseUserOrdersReturn;
20
+ export declare function orderFromSnapshotItem(item: OrderSnapshotItem): Order | null;
21
+ /**
22
+ * Apply a subscribe-time `orders` snapshot to the current list.
23
+ *
24
+ * The snapshot carries RESTING orders only, so — unlike the balances one — it
25
+ * is not the whole list this hook shows. Replacing wholesale would erase every
26
+ * filled or cancelled order the user just placed, so it reconciles through
27
+ * the same version-first ordering as {@link mergeOrders}, with its cap applied
28
+ * by age.
29
+ *
30
+ * It IS complete for the persisted resting set, so absence identifies rows that
31
+ * need resolution — but it is not itself a terminal-state tombstone. On a fast
32
+ * reconnect persistence may lag a newer resting event retained from the prior
33
+ * connection, while an order that really filled or was cancelled during the
34
+ * outage is absent for the same reason: it no longer rests. The pure merge
35
+ * therefore keeps omitted resting rows and reports their ids so the caller can
36
+ * issue the targeted `getOrder` required by the shared order contract. That
37
+ * point read is cache-first and returns the state/version that can be ranked.
38
+ * Terminal rows are kept exactly as before: the snapshot never carried them,
39
+ * so their absence says nothing.
40
+ *
41
+ * A snapshot row is ranked against the order already held on `version`. The
42
+ * snapshot wins when its version is equal or higher, because it is the final
43
+ * state for that sequencer step; a lower version loses. A versioned local row
44
+ * also wins over an unversioned snapshot: the latter cannot be ranked and may
45
+ * be persisted state lagging the previous connection's live stream. When both
46
+ * sides are unversioned, the pre-counter fallback keeps the snapshot's original
47
+ * precedence instead of comparing incompatible timestamps; that also permits a
48
+ * validly-null `updatedAt`.
49
+ *
50
+ * A snapshot row is LAYERED over the order it already knows rather than
51
+ * replacing it. `OrderSnapshotItem` is not a whole `Order`: it carries no
52
+ * `postOnly`, `expirationDate`, `positionSide`, `terminalReason` or fee
53
+ * aggregates. Substituting a winning snapshot row would otherwise erase every
54
+ * one of those — including `postOnly`, where absence is never evidence of
55
+ * `false`. Spreading the row over the existing order lets the snapshot own
56
+ * exactly the fields it describes and leaves the rest standing.
57
+ *
58
+ * The fee aggregates are the one part that can then go stale rather than
59
+ * missing: they accumulate with fills, and a fill this connection never saw
60
+ * moves them. So a snapshot row that reports MORE filled quantity than the row
61
+ * it supersedes schedules the debounced REST re-read, which is the only source
62
+ * for them. A snapshot that changes nothing about the fill state schedules
63
+ * nothing, so a quiet reconnect still costs no request.
64
+ *
65
+ * `hasUndescribableRow` reports rows this version declined, `hasOfflineFill`
66
+ * rows whose fills this connection never saw, and `missingRestingOrderIds`
67
+ * names snapshot omissions that need point reads. The first two let the caller
68
+ * schedule the debounced list re-read; the last must not use a list page because
69
+ * an old order can fall outside it.
70
+ *
71
+ * Pure, and called with the current list read from a ref rather than from
72
+ * inside a state updater — an updater must stay free of side effects, and its
73
+ * signals exist precisely to drive those reads.
74
+ */
75
+ export declare function applyOrderSnapshot(current: Order[], items: OrderSnapshotItem[], limit: number): {
76
+ orders: Order[];
77
+ hasUndescribableRow: boolean;
78
+ hasOfflineFill: boolean;
79
+ missingRestingOrderIds: string[];
80
+ };
81
+ /**
82
+ * The statuses the subscribe-time snapshot treats as resting.
83
+ *
84
+ * Mirrors the server's own `SNAPSHOT_RESTING_ORDER_STATUSES` — an order in one
85
+ * of these is still working on the book, so the snapshot carries it and its
86
+ * absence therefore means it stopped resting. Every other status is terminal
87
+ * or post-trade, never carried, so absence says nothing about it.
88
+ *
89
+ * The two sets must not drift: a status the server started treating as resting
90
+ * but this one does not would put its orders back in the stale-forever case
91
+ * this drop exists to fix, and one this set claims but the server does not
92
+ * would delete rows on an absence that means nothing. Exported so
93
+ * `useUserOrders.test.ts` can pin it against the Rust constant directly.
94
+ *
95
+ * A `Record<..., true>` over a subset of `OrderStatus`, read through
96
+ * `Object.hasOwn`, for the same reasons as {@link asKnown}: no prototype walk,
97
+ * and the union's own membership is checked by the compiler.
98
+ */
99
+ export declare const SNAPSHOT_RESTING_STATUSES: Partial<Record<OrderStatus, true>>;
100
+ /**
101
+ * Map snapshot rows onto the REST model, reporting whether any was declined.
102
+ *
103
+ * Split out of {@link applyOrderSnapshot} because it needs no view of the
104
+ * current list, which makes the mapping — and the decline rule that governs it
105
+ * — testable on its own.
106
+ */
107
+ export declare function snapshotOrderRows(items: OrderSnapshotItem[]): {
108
+ rows: Order[];
109
+ hasUndescribableRow: boolean;
110
+ };
111
+ /**
112
+ * Reconcile a REST read against live state, ranking on `version` first.
113
+ *
114
+ * The resync runs with the subscription open, so `fetched` may already be stale
115
+ * by the time it lands. Three cases:
116
+ *
117
+ * - In both: when either row has `version`, the versioned side wins; when both
118
+ * do, the incoming REST row wins on `>=` because it is that step's final
119
+ * state. Only when neither has a version does `updatedAt` arbitrate.
120
+ * - Live only: keep it. Either it was placed over the socket after the read
121
+ * started, or it is an older row the page no longer reaches — the two are
122
+ * indistinguishable here, which is why the cap is applied by age below
123
+ * rather than by which side a row came from.
124
+ * - REST only: take it. This is the order the resync exists to recover.
125
+ *
126
+ * The union is then sorted newest-first by `createdAt` and truncated to
127
+ * `limit`, so the row dropped at the cap is the genuinely oldest one. A missing
128
+ * or unparseable `createdAt` sorts last rather than to the top.
129
+ */
130
+ export declare function mergeOrders(current: Order[], fetched: Order[], limit: number): Order[];
131
+ /**
132
+ * Create an Order object from an OrderPlaced event
133
+ */
134
+ export declare function orderFromEvent(event: OrderEvent): Order | null;
135
+ /**
136
+ * Update an existing Order with data from a WebSocket event
137
+ */
138
+ export declare function updateOrderFromEvent(order: Order, event: OrderEvent): Order;