@totalis/hip4-client 0.0.0-stage → 0.73.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.
Files changed (74) hide show
  1. package/CHANGELOG.md +1903 -0
  2. package/LICENSE +202 -0
  3. package/README.md +143 -2
  4. package/dist/api-keys.d.ts +118 -0
  5. package/dist/api-keys.js +104 -0
  6. package/dist/audience-contract.d.ts +52 -0
  7. package/dist/audience-contract.js +1 -0
  8. package/dist/base.d.ts +41 -0
  9. package/dist/base.js +60 -0
  10. package/dist/client.d.ts +16 -0
  11. package/dist/client.js +15 -0
  12. package/dist/controller.d.ts +53 -0
  13. package/dist/controller.js +63 -0
  14. package/dist/errors.d.ts +3 -0
  15. package/dist/errors.js +3 -0
  16. package/dist/flow-errors.d.ts +62 -0
  17. package/dist/flow-errors.js +70 -0
  18. package/dist/generated/account-read.d.ts +2015 -0
  19. package/dist/generated/account-read.js +1 -0
  20. package/dist/generated/api-keys.d.ts +1303 -0
  21. package/dist/generated/api-keys.js +1 -0
  22. package/dist/generated/browse.d.ts +965 -0
  23. package/dist/generated/browse.js +1 -0
  24. package/dist/generated/client.d.ts +104 -0
  25. package/dist/generated/client.js +1 -0
  26. package/dist/generated/errors.d.ts +467 -0
  27. package/dist/generated/errors.js +1792 -0
  28. package/dist/generated/maker.d.ts +47 -0
  29. package/dist/generated/maker.js +1 -0
  30. package/dist/generated/openapi.d.ts +10867 -0
  31. package/dist/generated/openapi.js +1 -0
  32. package/dist/generated/operator.d.ts +7 -0
  33. package/dist/generated/operator.js +1 -0
  34. package/dist/generated/realtime.d.ts +1486 -0
  35. package/dist/generated/realtime.js +1 -0
  36. package/dist/generated/vault-abi.d.ts +49 -0
  37. package/dist/generated/vault-abi.js +70 -0
  38. package/dist/generated/version.d.ts +24 -0
  39. package/dist/generated/version.js +183 -0
  40. package/dist/hypercore.d.ts +111 -0
  41. package/dist/hypercore.js +132 -0
  42. package/dist/maker.d.ts +206 -0
  43. package/dist/maker.js +608 -0
  44. package/dist/money.d.ts +59 -0
  45. package/dist/money.js +66 -0
  46. package/dist/operator.d.ts +4 -0
  47. package/dist/operator.js +4 -0
  48. package/dist/pagination.d.ts +20 -0
  49. package/dist/pagination.js +27 -0
  50. package/dist/partner.d.ts +71 -0
  51. package/dist/partner.js +66 -0
  52. package/dist/realtime.d.ts +19 -0
  53. package/dist/realtime.js +10 -0
  54. package/dist/request.d.ts +115 -0
  55. package/dist/request.js +190 -0
  56. package/dist/signer.d.ts +51 -0
  57. package/dist/signer.js +90 -0
  58. package/dist/stream.d.ts +142 -0
  59. package/dist/stream.js +331 -0
  60. package/dist/totalis.d.ts +719 -0
  61. package/dist/totalis.js +1251 -0
  62. package/dist/typed-data.d.ts +330 -0
  63. package/dist/typed-data.js +340 -0
  64. package/dist/ui.d.ts +54 -0
  65. package/dist/ui.js +77 -0
  66. package/dist/wallet-session.d.ts +52 -0
  67. package/dist/wallet-session.js +63 -0
  68. package/examples/browser-wallet.html +69 -0
  69. package/examples/browser-wallet.mjs +57 -0
  70. package/examples/node-bot.mjs +57 -0
  71. package/examples/onboard.mjs +132 -0
  72. package/examples/partner-frontend.mjs +44 -0
  73. package/examples/partner-server.mjs +22 -0
  74. package/package.json +105 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,1903 @@
1
+ # Changelog
2
+
3
+ `@totalis/hip4-client` follows [semantic versioning](https://semver.org).
4
+ The contract version the generated types come from is `sdkVersion` in `./version`.
5
+
6
+ ## 0.73.0
7
+
8
+ A follower's copied trades, what copying each trader came to, and which of
9
+ their fills copies made (TT-2486); the chain-agent registry's `SET_AGENT`
10
+ Combo copy agents and the Combo copy budget (TT-2487).
11
+ Generated from contract `201.0.0-copy-budget`. Additive.
12
+
13
+ ### Added
14
+
15
+ - `listCopyTrades` (`GET /v1/me/copy-trades`): your copy journal, newest
16
+ first, optionally for one `leader`. Each row is a followed trader's trade
17
+ and what became of your copy: `PENDING`, `COPIED`, `PARTIAL`, `SKIPPED`
18
+ with a `reason`, or `FAILED`.
19
+ - `getCopySummary` (`GET /v1/me/copy-summary`): per trader, copies filled,
20
+ skipped and failed, USDC `bought` and `sold`, copied shares still `held`,
21
+ and whether those give the P&L (`complete`).
22
+ - `listCopiedFills` (`GET /v1/me/copy-fills?tids=&from=&through=`): which
23
+ of up to 100 of your fills, by Hyperliquid trade ID, in a span of at most
24
+ 31 days, copies made, with the copied trade and its `leader`.
25
+ - `HyperevmKeeperOperationKind` (internal registry): `SET_AGENT`, a relayed
26
+ vault agent grant or revoke.
27
+ - Combo copy agents: `requestComboCopyAgent`, `grantComboCopyAgent`,
28
+ `confirmComboCopyAgent`, `revokeComboCopyAgent` and
29
+ `switchOffComboCopyAgent` (`/v1/me/copy-agents/combo*`). The key Combo
30
+ auto-copy signs with, the account's vault `AgentGrant` for it relayed to
31
+ `setAgent`, its confirmation once on chain, an on-chain revoke, and
32
+ switching it off. `getCopyAgents` adds `combo`.
33
+ - `getCopyBudget` and `setCopyAllocation` (`/v1/me/copy-budget`): the Combo
34
+ copy allocation and the budget the sweeper leaves in the vault for Combo
35
+ copying.
36
+
37
+ ## 0.72.0
38
+
39
+ Emoji reactions on market comments (TT-2399), and a named refusal for a
40
+ core copy key on another account (TT-2485).
41
+ Generated from contract `196.0.0-copy-engine`. Additive.
42
+
43
+ ### Added
44
+
45
+ - Comment reactions: `reactComment` and `unreactComment`
46
+ (`PUT` and `DELETE /v1/comments/{comment_id}/reactions/{reaction}`) give and
47
+ take back one of `fire`, `laugh`, `mind_blown`, `cry`, `rocket` and `skull`.
48
+ Every comment gains `reactions`: each reaction it has, with its `count` and
49
+ whether you gave it (`reacted`).
50
+
51
+ ### Changed
52
+
53
+ - `requestCoreCopyAgent` (`POST /v1/me/copy-agents/core`) can answer
54
+ 409 `STATE_CONFLICT` while a key is active on another account: switch it
55
+ off first, or renew for the active key's account.
56
+
57
+ ## 0.71.0
58
+
59
+ Server-held copy agents for core auto-copy (TT-2484), users, cash-outs and
60
+ open positions in partner reports (TT-2541), and public trader profiles that
61
+ start on (TT-2539).
62
+ Generated from contract `194.0.0-partner-users`. Additive, except that public
63
+ profiles now start on.
64
+
65
+ ### Added
66
+
67
+ - Partner reports (TT-2541): `report()` (`GET /v1/partner/report`) adds
68
+ `users` (wallets you admitted and the accounts they created, all time),
69
+ `open_tickets` (your users' open positions and their stake), and per day
70
+ and in total `cashouts`, `cashout_volume`, `active_traders` and
71
+ `new_accounts`. In `totals`, `active_traders` counts each account once over
72
+ the range.
73
+
74
+ - Copy agents (TT-2484): `requestCoreCopyAgent`
75
+ (`POST /v1/me/copy-agents/core`) makes the key core auto-copy signs with,
76
+ which the account approves with `approveAgent` in the named slot
77
+ `TotalisCopy`; `confirmCoreCopyAgent` (`POST .../core/confirm`) activates it
78
+ once Hyperliquid lists it; `getCopyAgents` (`GET /v1/me/copy-agents`) reads
79
+ the active key and any replacement waiting for approval; and
80
+ `switchOffCoreCopyAgent` (`DELETE /v1/me/copy-agents/core`) stops copying at
81
+ once. New schemas `CopyAgent` and `CopyAgents`.
82
+
83
+ ### Changed
84
+
85
+ - Public trader profiles start on (TT-2539). A new account's profile is public
86
+ as soon as it exists, and every existing profile that never used the switch
87
+ was turned on, so `getIdentity` (`GET /v1/me`) reports `public_profile: true` for them, including
88
+ accounts without a username. `setPublicProfile` (`PUT /v1/me/public-profile`)
89
+ still turns it off, now also before the account has a username, and turning
90
+ it on still needs one. While on, a profile links the account wallet to its
91
+ username in `GET /v1/traders/{username}` and the leaderboards.
92
+
93
+ ## 0.70.0
94
+
95
+ A named refusal for a sign-in without Google, email or X (TT-2519, TT-2537).
96
+ Generated from contract `192.0.0-sign-in-required`. Additive.
97
+
98
+ ### Added
99
+
100
+ - `bindEmbeddedWallet` refuses a new account whose Privy user has no Google,
101
+ email or X login linked, such as one signed in only with an external
102
+ wallet, with the new error code
103
+ `SIGN_IN_REQUIRED` (403) instead of `ACCESS_REQUIRED` (TT-2519). An X
104
+ login now opens an account like Google or email (TT-2537).
105
+ On `bindEmbeddedWallet`, `ACCESS_REQUIRED` now means only that no invite has
106
+ been redeemed; wallet sign-in keeps its meaning.
107
+
108
+ ## 0.69.0
109
+
110
+ Vault run-off (TT-2260), X pictures on the leaderboard (TT-2318), a gas
111
+ ceiling on sponsored work (TT-2338), no generated usernames (TT-2299),
112
+ perp marks for price charts (TT-2335), live
113
+ games on sports cards and detail (TT-2306), Combos of at most 5 legs, and
114
+ games in play on browse, live scores over the market stream and score
115
+ timelines (TT-2371), market comments (TT-2297), their moderation (TT-2410),
116
+ holder badges and the holders filter (TT-2411), up to three suggested Combos,
117
+ held chances (TT-2366), partner reports (TT-2420), market list cursors
118
+ that continue across catalog generations (TT-2425), a named refusal for an
119
+ accept beside another in flight (TT-2259), the account's X picture from the
120
+ server (TT-2443), sponsored deposits from 0.10 USDC (TT-2444), the
121
+ funded-accept wording that gives a transfer sent before `fund_by` two more
122
+ seconds to land (TT-2259), the net stake on entry RFQs (TT-2419) and the
123
+ discovery cards of suggested Combo legs (TT-2475), opt-in public
124
+ trader profiles (TT-2481) and follows with copy settings (TT-2482).
125
+ Generated from contract `191.0.0-follows`.
126
+ Breaking only for callers of the removed operation and RFQs of more than 5
127
+ legs.
128
+
129
+ ### Added
130
+
131
+ - Follows and copy settings (TT-2482): `followTrader` and `unfollowTrader`
132
+ (`PUT` and `DELETE /v1/me/follows/{username}`) follow a public trader and
133
+ set the follow's core and Combo copy settings, `listFollows`
134
+ (`GET /v1/me/follows`) lists them, and `getCopySettings` and
135
+ `setCopySettings` (`/v1/me/copy-settings`) read and set the pause and daily
136
+ caps across every follow. `getTrader` gains `followers` and `following`, and
137
+ the new error codes `FOLLOW_SELF` and `FOLLOW_LIMIT_REACHED` refuse following
138
+ oneself or more than 100 traders.
139
+ - Public trader profiles (TT-2481): `setPublicProfile`
140
+ (`PUT /v1/me/public-profile`) turns the account's profile on or off, and
141
+ `getTrader`, `listTraderTrades`, `listTraderPositions` and `getTraderPnl`
142
+ (`GET /v1/traders/{username}` and its `trades`, `positions` and `pnl`) read
143
+ an opted-in trader. `VenueIdentity` and both leaderboards' traders gain
144
+ `public_profile`, and the new error code `USERNAME_REQUIRED` refuses turning
145
+ a profile on without a username.
146
+ - `SuggestedCombo` (`GET /v1/suggested-combo`) requires `cards`: the browse
147
+ contract 4 discovery card each leg was picked from, in leg order, as read
148
+ when it was quoted, so a client can draw a leg that is not on its own page
149
+ (TT-2475).
150
+ - `EntryRfq` (`GET /v1/rfqs`, `GET /v1/rfqs/{rfq_id}`, snapshot `open_rfqs`)
151
+ and the entry `RFQ_CREATED` payload carry `net_stake`, what the vault backs
152
+ if a quote is accepted: `stake - floor(stake * taker_fee_bps / 10000)` with
153
+ the vault's current taker fee, the one every quote must carry. `stake` stays
154
+ gross and quotes still sign it. Absent while the server does not know the
155
+ taker fee (TT-2419).
156
+ - `DashboardQuotes` (`GET /v1/makers/{maker_id}/quotes`) requires `net_stake`
157
+ on each quote: its stake less its own taker fee (TT-2419).
158
+ - `VenueIdentity` (`GET /v1/me`) and comment authors carry `picture_url`, the
159
+ profile picture of the X account linked to the account's Privy login, the
160
+ same one the leaderboards show; absent when the server has none.
161
+ `POST /v1/me/picture` (`refreshPicture`) reads it from Privy now; call it
162
+ right after the user links or unlinks X.
163
+ - `ErrorCode` adds `ACCEPTANCE_IN_FLIGHT` (409, `REFRESH`), and Accept quote
164
+ lists it: an account has one entry acceptance in flight at a time, so
165
+ accepting an entry quote while another awaits its maker or its trade is
166
+ refused with it instead of `STATE_CONFLICT`. Nothing was created; accept a
167
+ fresh quote once that acceptance's operation ends.
168
+ - Wallet challenges accept the exact bundled iOS origin `capacitor://localhost`
169
+ when it is registered in the service allowlist. Existing HTTPS origins and
170
+ wallet-signature requirements are unchanged.
171
+ - Partner reports (TT-2420): `createPartnerServer(...).report({ from, to })`
172
+ (`GET /v1/partner/report`) returns your partner's fees per UTC day, your
173
+ terms and, all time, what you earned, were paid and are owed, with every
174
+ payout and its transfers. It takes your server key; omit the range for the
175
+ 30 days through today.
176
+ - `signInWithWallet({ serverKey })`: a partner signing its users in from its
177
+ own servers passes its `tpk_v1_` server key, and the sign-in is rate limited per
178
+ partner instead of per source address (TT-2424). The origin must be one the
179
+ partner owns; the wallet still signs. Server-side only.
180
+ - Vault v1.1 maker withdrawals: `controllerTransactions(...).withdraw(amount,
181
+ to)` builds `withdrawMaker`, which pays at once. `requestWithdraw`,
182
+ `executeWithdraw` and `cancelWithdraw` stay for a vault v1 maker.
183
+ - Market comments (TT-2297): `GET /v1/comments` lists a question's or
184
+ standalone outcome's top-level comments, most liked or newest first;
185
+ `GET /v1/comments/{comment_id}/replies` lists a comment's replies. A
186
+ signed-in session posts, edits, deletes, likes and unlikes with
187
+ `POST /v1/comments`, `PUT` and `DELETE /v1/comments/{comment_id}` and
188
+ `PUT` and `DELETE /v1/comments/{comment_id}/like`.
189
+ - Comment moderation (TT-2410): a comment carries `removed` when a moderator
190
+ deleted it, and a comment page carries `pinned`, the comment a moderator
191
+ pinned to lead the thread, on a thread's first page only. A muted account's
192
+ posts and edits are 403 `FORBIDDEN`.
193
+ - Comment holders (TT-2411): a comment carries `holder` when its author holds
194
+ an open Combo on its market now, null when that is not known.
195
+ `GET /v1/comments?filter=holders` lists only holders' comments.
196
+ - `GET /v1/suggested-combo` carries `combos`, up to three suggested Combos
197
+ that share no outcome. `combo`, the first of `combos` or null, is
198
+ deprecated and goes in the next release.
199
+ - `signRunOffClaim({ vaultAddress })` signs an Exit of the account's free cash
200
+ in a vault running off to the account's own wallet; send it with
201
+ `sendRunOffClaim` (`POST /v1/me/run-off-claims`) and follow its operation
202
+ with `waitForOperation`.
203
+ - Balances carry `run_off`: cash per vault running off, never part of
204
+ `amount`, with any claim still in flight as `claim`. A position carries
205
+ `vault_address` and `cashout_available`; a core exit carries
206
+ `vault_address`.
207
+ - A cash-out of a position on a vault running off returns `STATE_CONFLICT`.
208
+ - Both leaderboards' traders carry `picture_url`, the profile picture of the X
209
+ account linked to the trader's Privy login, which clients show in place of
210
+ the generated avatar.
211
+ - `ErrorCode` adds `GAS_PRICE_ABOVE_CEILING` (503, `BACKOFF`): creating a
212
+ Combo RFQ or a cash-out is refused while HyperEVM gas is above the venue's
213
+ sponsorship ceiling. Retry after `Retry-After`.
214
+ - An RFQ's `status` adds `DECLINED` and the stream adds `RFQ_DECLINED`, for
215
+ RFQs makers declined before declines were removed (TT-2431); no RFQ ends
216
+ `DECLINED` now. `watchQuotes` empties and `onRfq` drops the RFQ on it, as on
217
+ `RFQ_CANCELLED`.
218
+ - Types for `GET /v1/perp-marks`, a perp's mark price on a fixed step recorded
219
+ from Totalis's own Hyperliquid node, and for the market stream's opt-in
220
+ `publication` frame (`publication_freshness`), which proves how far a
221
+ socket is current.
222
+ - Browse and search cards carry `estimated_live_until` (TT-2306): for a
223
+ scheduled single sports contest, its start plus its league's reviewed usual
224
+ game length, so `[date_at, estimated_live_until)` is when it is in play. A
225
+ live game feed holds it open while the game runs long and closes it when
226
+ the game ends. Null otherwise; never a trading cutoff. Every default browse
227
+ page, All included, lists cards inside that window first.
228
+ - `Question` carries the same `estimated_live_until` for its markets, and
229
+ `MarketDetail` read with `contract=4` carries its matchup's: its question's,
230
+ else its game's, else its own.
231
+ - Both also carry `scoreboard`: the matchup's game as the live game feed last
232
+ read it (`status`, `period`, `clock`, `outs`, both `competitors` with
233
+ `score` in the matchup's own order, `last_play`, `refreshed_at`), or null
234
+ when the feed does not cover the game or its reading is stale. Display only,
235
+ never a result.
236
+ - Browse queries take `live: true` (TT-2371): only the cards in play at
237
+ publication, for All or one `category`, in either browse sort; a
238
+ subcategory, frequency or date window beside it returns `INVALID_QUERY`.
239
+ Results echo it as `filters.live`. Every browse and search result carries
240
+ `live`: the publication's count of cards in play, `total` and per
241
+ configured category (`categories`, `{ value, count }`), each equal to that
242
+ live page's total, or `UNAVAILABLE` when the result's other counts are.
243
+ - The market stream's opt-in `scoreboards` frame (TT-2371): a subscription
244
+ that sets `scoreboards` gets every selected game's `scoreboard`, complete
245
+ after each snapshot and then on every change.
246
+ - Types for `GET /v1/markets/{outcome_id}/score-timeline` and
247
+ `GET /v1/questions/{question_id}/score-timeline` (TT-2371): the matchup's
248
+ score after each scoring play at the feed's wall-clock time, for a game
249
+ chart, or a null `timeline`.
250
+
251
+ ### Changed
252
+
253
+ - `openPosition` (`POST /v1/rfqs`) takes 1 to 5 legs, down from 50; more
254
+ return `400 INVALID_REQUEST`.
255
+ - A reference's `chance` holds the newest evidence, an execution or a book
256
+ midpoint at most 0.10 wide, kept inside the live book (TT-2366): on a book
257
+ at most 0.50 wide at any age, and on a wider, one-sided or empty book for
258
+ 20 minutes. `chance_basis` adds `HELD` for a chance that is neither the
259
+ current midpoint nor the unclamped last trade. A one-sided or empty book is
260
+ published `AVAILABLE` while it has a `mark` (a chance, else the best bid,
261
+ else 0 with asks only), with the missing side null and `value` equal to
262
+ `mark`. Reference closes record the shown chance of
263
+ any basis, not only midpoints.
264
+ - `GET /v1/markets` no longer returns `409 STALE_CURSOR`: its cursor continues
265
+ by native ID when a new catalog generation is published, so pages can name
266
+ different `catalog_generation` values (TT-2425).
267
+ - `createDeposit` (`POST /v1/me/deposits`) admits deposits from 0.10 USDC
268
+ (`100000`) from a Totalis embedded wallet, down from 1 USDC (TT-2444). Any
269
+ other wallet still moves at least 1 USDC, its floor for every sponsored way
270
+ out.
271
+
272
+ ### Removed
273
+
274
+ - `generateUsername` (`POST /v1/me/username`) and its `GeneratedUsername`
275
+ schema. An app picks the username and sets it with `setUsername`
276
+ (`PUT /v1/me/username`).
277
+
278
+ ### Fixed
279
+
280
+ - `sendAcceptance` no longer discards a bridge because a resent accept was
281
+ refused (TT-2259). When the first send's answer was lost and the SDK's resend
282
+ under the same `Idempotency-Key` met a 401 (the session lapsed), the bridge
283
+ was recorded `DISCARDED` and never sent, even though the venue held the first
284
+ send's acceptance. A resend's refusal now ends the attempt only if the venue
285
+ checks it after replaying a stored acceptance (a gone price, a bad
286
+ signature). A resend's 401, 403 or 429, which the venue checks before the
287
+ replay, and a 5xx or an answer cut off mid-body, no longer discard the
288
+ bridge: the SDK reads the acceptance and moves the bridge from what it finds. If that read fails too, the bridge stays unsent
289
+ and the error reports `mayStillRun: true`, with `resend()`, so recovery
290
+ decides after re-authenticating.
291
+ - `recoverAcceptance` works without a signer: it checks the record's account
292
+ against the session's wallet (`GET /v1/me`), since recovery signs nothing.
293
+
294
+ ## 0.68.0
295
+
296
+ Every expired operation names why (TT-2315). Generated from contract
297
+ `165.0.0-expiry-reasons`; an older venue simply sends fewer reasons.
298
+
299
+ ### Changed
300
+
301
+ - `OperationFailureReason` adds `DEADLINE_BEFORE_CLAIM`,
302
+ `AUTHORIZATION_TOO_CLOSE`, `SIGNER_QUOTE_LIFE`, `SIMULATION_REVERTED`,
303
+ `QUARANTINE_EXPIRED` and `ATTESTATION_EXPIRED`. An operation's
304
+ `failure_reason`, and `OPERATION_UPDATED`'s, can carry any of them on
305
+ `EXPIRED_UNEXECUTED`.
306
+ - `entryFailure` returns the operation's own reason for every reason but
307
+ `INSUFFICIENT_CASH`, which it still words as `INSUFFICIENT_CASH` or
308
+ `CORE_MOVE_MISSED`. `EntryFailure` widens to match: code that handles it
309
+ exhaustively needs a case for each new reason.
310
+
311
+ ## 0.67.0
312
+
313
+ Taker flow fixes (TT-2268). Additive: 0.66 code runs unchanged.
314
+
315
+ ### Added
316
+
317
+ - `bestBid(minLifeSeconds, minPrice)`: an optional price floor in USDC base
318
+ units; no bid below it is chosen.
319
+ - `RetryPolicy.maxRetryAfterMs` (default 30 s). A BACKOFF answer whose
320
+ Retry-After is longer is no longer waited out: the call throws at once, for
321
+ example `RATE_LIMITED`, with `retryAfterMs` set.
322
+ - `StreamClosedError.commandSent` and `TotalisStream.closeError()`.
323
+
324
+ ### Changed
325
+
326
+ - A follow cut off by a stream closed for good rejects with the server's
327
+ close reason (for example `STREAM_REPLACED`), not a generic `closed`. When
328
+ it follows a command already sent (`waitForOperation`, `waitForCoreExit`,
329
+ `sendWithdrawal`, `waitForWithdrawal`), the error has `commandSent` and
330
+ `normalizeError` reports `mayStillRun: true`.
331
+ - An `AcceptanceResult`'s `bridged` reads the bridge as it stands now, so it
332
+ turns `landed: "yes"` once Hyperliquid answers `ok`, and reads undefined
333
+ once a bridge is refused or discarded unsent.
334
+ - `openPosition` takes and signs a fresh quote once when the accept is
335
+ refused with `QUOTE_EXPIRED` or `QUOTE_REPLACED`; `onSigned` gets the new
336
+ record. A second refusal, or no fresh quote within `quoteTimeoutMs`, throws
337
+ the refusal.
338
+ - Deposit, withdrawal and exit signing windows are set on the venue clock the
339
+ stream tracks once it has synced. Signing never waits for the stream, so a
340
+ window signed on a fresh instance before its first sync uses the device
341
+ clock; start the stream first on devices whose clock may be off.
342
+ - Documented that an acceptance read after the trade settled, for example by
343
+ `recoverAcceptance`, can be `FILLED` or `FAILED`, both with `operationId`.
344
+
345
+ ## 0.66.1
346
+
347
+ Combos close at a market's admission cutoff (TT-2271). No type changes.
348
+
349
+ ### Changed
350
+
351
+ - `combo` is `CLOSED` with `OUTSIDE_WINDOW` and a null `opens_at` once a
352
+ market's result can be known: a price market from its observation time, a
353
+ policy rate from its scheduled decision. A sports game stays open in play
354
+ until its resolution backstop. RFQs refuse such legs as before.
355
+
356
+ ## 0.66.0
357
+
358
+ A lighter HyperCore read for Cash (TT-2277). Additive: 0.65 code runs unchanged.
359
+
360
+ ### Added
361
+
362
+ - `GET /v1/hypercore/balance` returns the session account's HyperCore spot
363
+ USDC, perps cash, account mode and HIP-4 positions in one read, on mainnet
364
+ and testnet. It reads no orders or fill history, so it answers even when
365
+ the portfolio's fill history is unavailable.
366
+ - HyperCore funding (`/v1/hypercore/portfolio` and the new route) carries
367
+ `spot_usdc_total` and `spot_usdc_hold`; `spot_usdc` stays total minus hold.
368
+ ## 0.65.2
369
+
370
+ The package is now `@totalis/hip4-client`, published to public npm. Install
371
+ it under the new name and change your imports from
372
+ `@totalistrading/hip4-client` to `@totalis/hip4-client`; nothing else
373
+ changes. 0.65.1 was tagged under the old name but never published.
374
+
375
+ ## 0.65.1
376
+
377
+ The first release on public npm (`registry.npmjs.org`), under Apache-2.0, with
378
+ no registry configuration or token needed. Remove any
379
+ `@totalistrading:registry=https://npm.pkg.github.com` line from your `.npmrc`.
380
+ The code is the same as 0.65.0; 0.65.0 and earlier stay on GitHub Packages.
381
+ The README is now a short overview; the full guide is at
382
+ [docs.totalis.trade/hyperliquid/sdk](https://docs.totalis.trade/hyperliquid/sdk).
383
+
384
+ ## 0.65.0
385
+
386
+ A failed operation says why (TT-2261). Additive: 0.64 code runs unchanged.
387
+
388
+ ### Added
389
+
390
+ - `Operation` and the `OPERATION_UPDATED` payload carry an optional
391
+ `failure_reason`: `INSUFFICIENT_CASH` when an accept ended
392
+ `EXPIRED_UNEXECUTED` because the taker's Cash did not cover the stake, and
393
+ absent otherwise. `waitForOperation` resolves with it, so you no longer need
394
+ the RFQ's `terminal_reason`.
395
+ - `entryFailure(record, operation)` names why an entry did not trade, for the
396
+ message to show: `INSUFFICIENT_CASH` (not enough Cash, including when the
397
+ planned Core cash landed) or `CORE_MOVE_MISSED` (the record planned Core
398
+ cash that Hyperliquid never confirmed moving before `fund_by`, so the user
399
+ may still have enough on HyperCore). It is `undefined` for any other
400
+ outcome. Pass the latest record, as `onRecord` last handed it back.
401
+ - `openPosition` returns the entry `record`, which follows each bridge update
402
+ `onSigned` gets.
403
+ - The `createRfq` error list includes `RFQ_GENERATION_STALE`,
404
+ `RFQ_GENERATION_IN_FLIGHT` and `COMBO_AUTOMATIC_DISABLED`, which the route
405
+ already returned.
406
+
407
+ ```ts
408
+ const opened = await totalis.openPosition({ legs, stake, core });
409
+ if (opened.operationId) {
410
+ const operation = await totalis.waitForOperation(opened.operationId);
411
+ if (operation.status !== "COMMITTED") {
412
+ const failure = entryFailure(opened.record, operation); // "INSUFFICIENT_CASH" | "CORE_MOVE_MISSED" | undefined
413
+ }
414
+ }
415
+ ```
416
+
417
+ Needs a venue with contract `163.0.0-operation-failure-reason`; against an
418
+ older venue `failure_reason` is absent and `entryFailure` returns `undefined`.
419
+
420
+ ## 0.64.0
421
+
422
+ A Combo entry posts its accept at once and moves Core cash only after the
423
+ maker takes it (TT-2125). The accept no longer waits up to 1.5 s for
424
+ Hyperliquid's answer to the bridge, and a declined, timed-out or not-admitted
425
+ entry never sends its bridge. Needs a venue that publishes `accept_before` on entry
426
+ quotes and `fund_by` and `server_time` on acceptances.
427
+
428
+ ### Changed
429
+
430
+ - `sendAcceptance` posts the accept first. The Core to HyperEVM bridge goes
431
+ only when the acceptance is `ACCEPTED` with a `fund_by` still ahead, and is
432
+ resent while unanswered until `fund_by`; an accept answered any other way
433
+ discards it. The result does not wait for Hyperliquid: its new `bridging`
434
+ promise carries the answer, and `bridge` (the answer) is gone.
435
+ - `signEntry` asks the signer for the quote, the bridge and the wallet
436
+ authorization at once. Pass `cash` (the `{ vault, wallet }` of a
437
+ `spendableCash` read) to plan without a balances read on the press; a plan
438
+ that fails then throws before the wallet is asked for anything. Without
439
+ `cash` it still reads the balances. `openPosition` takes `cash` too, and
440
+ otherwise reads the balances while the quotes arrive.
441
+ - `recoverAcceptance` now finishes the bridge: it sends a never-sent bridge
442
+ if the acceptance is `ACCEPTED` before its `fund_by` and discards it
443
+ otherwise, and resends a sent but unanswered one, the same bytes, within
444
+ that window. It takes `transport` and `onRecord`. A bridge moves only for
445
+ the record's own acceptance: when another record's acceptance took the
446
+ quote, the result reports it and this record's bridge is discarded.
447
+ While a never-sent bridge waits on a `PENDING_CONFIRM` acceptance, it and
448
+ a lost accept answer are read every 250 ms until 2 s past the maker's
449
+ deadline, so an early `ACCEPTED` still moves cash before `fund_by`.
450
+ - `fund_by` is judged by the latest the venue clock can read: a response's
451
+ new `server_time`, read from the database clock that sets `fund_by`, plus
452
+ the time since its request left. A skewed local clock or a delayed
453
+ response never sends late, and a bridge with no stamp to judge by is
454
+ discarded. An entry with a bridge reads its RFQ's quotes alongside the
455
+ accept for a tight stamp, since the held accept's own runs late by the
456
+ maker's wait. A first send whose `fund_by` passed while
457
+ `onRecord` saved `SENT` is not sent and records `DISCARDED`.
458
+ - Entry records carry `version: 2` and a `bridgeState` (`SENT`, `LANDED`,
459
+ `PROCESSED`, `REFUSED`, `DISCARDED`). `onRecord` on `sendAcceptance` and
460
+ `recoverAcceptance` (and `openPosition`'s `onSigned`) is awaited with the
461
+ record before the first send and gets it again with each new state:
462
+ persist it over the stored one. A record without `version`
463
+ (`LegacySignedEntry`, from 0.63 or older) is only read by
464
+ `recoverAcceptance`; `sendAcceptance` refuses it.
465
+ - `bridged` is set only once a bridge was sent: never for one never sent,
466
+ discarded or refused. A refused bridge after `ACCEPTED` leaves the result
467
+ `ACCEPTED`.
468
+ - `settleHypercore` checks its `deadline` before every send, not only by
469
+ timer, on its new `now` clock (epoch ms by default).
470
+ - `bestQuote()` and the quote book cut entry quotes off at their
471
+ `accept_before` instead of fixed margins; `bestQuote` takes no argument,
472
+ and the UI adapter's `minLifeSeconds` applies to cash-out quotes only. An
473
+ entry quote without `accept_before` is never offered.
474
+
475
+ ### Removed
476
+
477
+ - `EntryError` codes `QUOTE_SHORT`, `BRIDGE_LATE` and `BRIDGE_REFUSED`, with
478
+ its `hyperliquidError` and `bridged`, and `bridged` on `ApiError` and
479
+ `normalizeError`'s result: nothing is bridged before the accept any more.
480
+
481
+ ## 0.63.0
482
+
483
+ Fixes from a partner integration (TT-2258).
484
+
485
+ ### Changed
486
+
487
+ - `openPosition` and `cashOut` take `collectMs` (default 1,000): once `choose`
488
+ would take a quote, more quotes may arrive for that long, and `choose` picks
489
+ when the window ends, whether or not any did. The window ends sooner when
490
+ waiting would leave `choose` nothing. `collectMs: 0` takes the first quote
491
+ as before. A `Chooser` may be asked about a later time, so it must
492
+ depend only on its arguments.
493
+ - `signEntry` and `openPosition` without `core` throw `EntryError`
494
+ `INSUFFICIENT_FUNDS`, naming the shortfall, when the wallet is known to fall
495
+ short, instead of signing an entry the venue refuses.
496
+ - `issueApiKey` refuses a challenge whose `urn:totalis:scope:` resources differ
497
+ from the requested scopes. Key challenges now list the scopes they grant and
498
+ `urn:totalis:expires-in-days:<days>`.
499
+ - A transfer bid its buyer's free vault balance cannot pay is refused at
500
+ publish (`INVALID_REQUEST`, `transfer.price`) instead of timing out after the
501
+ owner accepts it.
502
+
503
+ ## 0.62.0
504
+
505
+ Hourly reference closes, so charts can show a market's trend past one day
506
+ (TT-2230). Generated from contract 161.
507
+
508
+ ### Added
509
+
510
+ - `GET /v1/markets/{outcome_id}/reference-closes` takes `bucket=HOUR`: each
511
+ UTC hour carries the close of its last observed minute, over a window of up
512
+ to 90 days (the default with no `from`/`to`), `limit` up to 2,184. Every
513
+ response now carries `bucket_seconds` (60 or 3600), and runs read
514
+ `[bucket, close, buckets]`. Minute closes are unchanged.
515
+
516
+ ## 0.61.0
517
+
518
+ Makers onboard and run headless (TT-2257): the /mm dashboard becomes read-only,
519
+ so every maker write goes through the SDK or the API. No API change.
520
+
521
+ ### Added
522
+
523
+ - `listApiKeys(client, { maker? })` reads every page of an account's or a
524
+ maker's keys; `revokeApiKey(client, keyId, { maker? })` revokes one and throws
525
+ the venue's `ApiError` otherwise.
526
+ - `QUOTING_BOT_SCOPES` (the maker scopes for a quoting bot, none of which move
527
+ vault money) and `COLLATERAL_SCOPES` (for `reduceCollateral`), with the
528
+ `KeyScope` and `KeyMetadata` types.
529
+ - `examples/onboard.mjs`: headless maker onboarding from the exported Totalis
530
+ wallet key: sign in, open and admit the maker, issue the quoting bot's key,
531
+ make the first deposit into the maker vault (only while it is empty on
532
+ chain) and start quoting. A rerun resumes and never deposits twice.
533
+
534
+ ### Changed
535
+
536
+ - `signInWithWallet`'s `origin` documentation: outside a browser a maker passes
537
+ the Totalis app's origin (`https://hip4.totalis.trade`, or
538
+ `https://hip4-staging.totalis.trade` on staging) and sends it as the Origin
539
+ header with every request on the session.
540
+
541
+ ## 0.60.1
542
+
543
+ The venue now refuses, with 409 `STATE_CONFLICT`, to replace or cancel a quote
544
+ while a taker's acceptance of it awaits the maker's answer, instead of
545
+ withdrawing the acceptance (TT-2254). That closes the window 0.60.0 left: an
546
+ acceptance recorded while a replacing quote was on its way. Generated from the
547
+ contract with the new 409 descriptions; no API change.
548
+
549
+ ### Changed
550
+
551
+ - `quote`, `bid` and `cancelQuote` can answer `ApiError` `STATE_CONFLICT`
552
+ (`retry: "REFRESH"`) when an acceptance of the quote awaits this maker's
553
+ answer: answer it (`confirm`, or `onAcceptance`) first. The documentation of
554
+ `AcceptancePendingError` and `cancelQuote` says so.
555
+
556
+ ## 0.60.0
557
+
558
+ A maker no longer withdraws the acceptances it knows of by quoting again
559
+ (TT-2253). An acceptance the venue records while a quote is already on its way
560
+ can still be withdrawn by it: the SDK checks what the stream and the
561
+ acceptances read have delivered, not the venue's state at publication.
562
+ Generated from contract 160; no API change.
563
+
564
+ ### Changed
565
+
566
+ - Maker (`createMaker`): replacing or cancelling a quote while a taker's
567
+ acceptance of it awaits the maker's answer makes the venue withdraw that
568
+ acceptance. `quote` and `bid` now throw `AcceptancePendingError` (`code`
569
+ `ACCEPTANCE_PENDING`, with `rfqId`, `quoteId` and `deadline`), publishing
570
+ nothing, on an RFQ where this maker holds an unanswered acceptance, and
571
+ `onRfq` holds such an RFQ back until the acceptance is answered or its
572
+ deadline passes. A restarted maker that quotes every RFQ `onRfq` hands it no
573
+ longer withdraws the acceptances its snapshot carries.
574
+ - `quote` and `bid` start the maker stream if needed and wait until it is live,
575
+ so the pending acceptances are known, and check again just before publishing.
576
+ After a snapshot that truncated `acceptances`, or a stream resumed from a
577
+ cursor (its replay has no end marker, and an acceptance delivered before the
578
+ saved cursor is not replayed), they and `onRfq` also wait until
579
+ `GET /v1/makers/{maker_id}/acceptances` has been read in full. While that
580
+ read fails, `quote` and `bid` throw its error and `onRfq` offers nothing,
581
+ retrying every second. That read needs `quote:read`, one of the maker
582
+ scopes. Acceptance deadlines are compared on the venue clock.
583
+ - `cancelQuote`: `ACCEPTED` means this maker already confirmed the quote.
584
+ Cancelling a quote whose acceptance awaits an answer withdraws the
585
+ acceptance; prefer `confirm(acceptance, "DECLINE")`.
586
+ ### Added
587
+
588
+ - `reduceCollateral` returns the job's `idempotencyKey`. Without
589
+ `signTransaction`, sign the returned `transaction` yourself and submit it to
590
+ `POST /v1/makers/{maker_id}/operations/{operation_id}/self-funded-transaction`
591
+ under that same `Idempotency-Key`, the only one the route admits for the job.
592
+ Before, a job returned without `signTransaction` could not be finished.
593
+
594
+ ### Changed (example)
595
+
596
+ - `examples/node-bot.mjs` bids on cash-outs only to buy back its own positions
597
+ (a transfer is paid from the maker wallet's own account balance, which it
598
+ does not fund) and confirms only while its `willing(acceptance)` check holds.
599
+
600
+ ## 0.59.0
601
+
602
+ Say where the cash is after a bridged entry that did not trade (TT-2219).
603
+ Generated from contract 160; no API change.
604
+
605
+ ### Added
606
+
607
+ - `AcceptanceResult.bridged` (`BridgedCash`: `{ amount, landed }`, amount in
608
+ USDC base units) for an entry that bridged from HyperCore, whatever its
609
+ status. Unless the entry's operation `COMMITTED`, that cash is in the
610
+ HyperEVM wallet, not on HyperCore: the next entry spends it first, or
611
+ `returnToCore` moves it back. `landed` is `"yes"` only on Hyperliquid's
612
+ `ok`; with no answer, a `processed` nonce (a lost refusal spends it too) or
613
+ after `recoverAcceptance` it is `"unknown"`.
614
+ - An accept refused after the bridge (an `ApiError` that cannot still run,
615
+ such as `QUOTE_EXPIRED`) and a `BRIDGE_LATE` `EntryError` carry the same
616
+ `bridged`; `normalizeError` copies it to `NormalizedError.bridged`.
617
+
618
+ ## 0.58.0
619
+
620
+ An opt-in maker quote lease, so takers stop spending their quote window on a
621
+ maker that has gone quiet (TT-2229). Generated from contract 160.
622
+
623
+ ### Added
624
+
625
+ - Maker (`createMaker`): `keepQuoteLease(leaseMs, onError?)` renews the lease
626
+ now and every third of `leaseMs` until the returned stop function, `close()`
627
+ or another `keepQuoteLease` call. `renewQuoteLease(leaseMs)`
628
+ (`PUT /v1/makers/{maker_id}/quote-lease`, 1000 to 60000 ms) arms or renews it
629
+ once and answers `{ lease_ms, expires_at }`; `releaseQuoteLease()`
630
+ (`DELETE`) disarms it and answers `{ released }`.
631
+ - Once a lease lapses, the venue cancels each open quote of the maker that no
632
+ taker is accepting, and each one it publishes after, until it renews or
633
+ releases the lease. Takers see `QUOTE_REMOVED` with `CANCELLED`, which
634
+ `watchQuotes` and `bestQuote` already honour. An acceptance already under way
635
+ runs to its confirm deadline as before. A maker without a lease sees no change.
636
+
637
+ ## 0.57.0
638
+
639
+ Partner helpers from the Liquid dogfood run (TT-2224). Generated from contract
640
+ 159; no API change.
641
+
642
+ ### Changed
643
+
644
+ - `stream.status === "live"` after a resumed account stream means the replay
645
+ has been applied. With publication freshness (the account default) the
646
+ stream stays `connecting` through the replayed events and goes live at the
647
+ first publication checkpoint, which the venue sends only after them. A
648
+ stream without publication freshness (the maker default) has no such marker
649
+ and is still live once subscribed. `stream.live()` and the flows wait the
650
+ same way, up to one 1 s heartbeat longer on a resume.
651
+ - A withdrawal or return to HyperCore with an unread balance throws
652
+ `BalanceUnknownError` (`component`: `VAULT_FREE` or `WALLET_USDC`), and a
653
+ deployment without exits to HyperCore (staging) throws
654
+ `ExitUnavailableError` from `signCoreExit`, `exitToCore`, `signReturnToCore`
655
+ and `returnToCore`, before anything is signed. Both used to be plain
656
+ `Error`s. `sendCoreExit` turns the venue's 503 `CORE_EXIT_UNAVAILABLE`,
657
+ which it answers only where no exit runs, into `ExitUnavailableError` (the
658
+ refusal as `cause`). `signReturnToCore` reads the exit route before it signs
659
+ the deposit leg. Entries still throw `EntryError` `BALANCE_UNKNOWN`.
660
+
661
+ ### Added
662
+
663
+ - `spendableCash(balance)` and `totalis.spendableCash()`: `{ vault, wallet,
664
+ total }` from `GET /v1/me/balances`, the reservation-aware figures the SDK
665
+ plans with. Each is `null` while unknown, never 0.
666
+ - `netPayout(quote)`, `netCashout(bid, position)`, `netOfProfitFee` and
667
+ `netStake`: what the user actually receives, by the vault's fee rules. The
668
+ profit fee is `floor((amount - net_stake) * fee_bps / 10000)` on a settlement
669
+ payout or sell-back price above the net stake; a transfer pays its price in
670
+ full. A quote with payout 9.18 USDC on a 3 USDC stake nets 9.118140 USDC.
671
+ - `normalizeError(error)`: any SDK failure as `{ code, message, retryable,
672
+ retry, requestId, status, mayStillRun, resend, cause }`. `mayStillRun` is
673
+ true when the command may have reached the venue (a lost response, an abort
674
+ or timeout in flight, `BACKOFF` after the resends, a proxy 5xx). Also on
675
+ `/errors`, with the error classes.
676
+ - `createUiAdapter(totalis, { onInvalidate, onCatalogStale })`: quotes with the
677
+ best one (`watchQuotes`), the venue clock (`serverNow`, `secondsLeft`),
678
+ `readInvalidated` revisions (and every resource each time the stream goes
679
+ live) for a query cache, and a catalog refresh only for a newer
680
+ `catalog_generation` than `catalogLoaded`. No framework dependency.
681
+ - `/maker`: `makerReadiness(client)` reads `GET /v1/me/maker`, admits an
682
+ indexed or self-service `PENDING` maker with `POST /v1/me/maker`, and
683
+ answers `NOT_INDEXED` instead of a 404 while the open transaction is not
684
+ indexed yet; `waitForMaker(client)` reads again until it is.
685
+
686
+ ## 0.56.0
687
+
688
+ An eligibility filter on the market list (TT-2226). Generated from contract
689
+ 158.
690
+
691
+ ### Added
692
+
693
+ - `eligibility` on `GET /v1/markets` (`ENABLED` or `DISABLED`) keeps only
694
+ markets in that state. A page can be short or empty while `has_more` is
695
+ true, and the cursor is bound to the filter.
696
+
697
+ ## 0.55.0
698
+
699
+ Cash-out RFQs carry the position's stake and payout (TT-2228). Generated from
700
+ contract 157.
701
+
702
+ ### Added
703
+
704
+ - `CashoutRfq` and the cash-out `RFQ_CREATED` payload require `net_stake` and
705
+ `payout`, atomic USDC strings: the position's `tickets(position_id).stake`
706
+ (after the taker fee) and `.payout`. The vault fixes both when the position
707
+ opens, so they hold at `decision_block`. A maker can price a transfer
708
+ without reading the ticket.
709
+
710
+ ## 0.54.0
711
+
712
+ Anonymous reads refuse query parameters they do not take (TT-2223).
713
+ Generated from contract 155. No code change for callers.
714
+
715
+ ### Changed
716
+
717
+ - A malformed query, a repeated parameter or one the operation does not list
718
+ is 400 `INVALID_QUERY` on every anonymous read. `field_violations` names an
719
+ unlisted parameter as `UNEXPECTED`, and a repeated one or a malformed value
720
+ (`limit=%GG`) as `INVALID`; a key that does not decode names nothing. This
721
+ covers markets, questions, series, history, recurring rounds, discovery,
722
+ search, taxonomy, market stats, config, definitions, deployment, suggested
723
+ Combo, RFQs and the market stream handshake. `/v1/markets?search=BTC` used to
724
+ answer an unfiltered page.
725
+ - `getDeployment`, `getSuggestedCombo`, `getMarketStats`, `getMarketDataConfig`
726
+ and `getMarketDefinitions` gain a 400 response; the rest list
727
+ `INVALID_QUERY` in `operationErrors`.
728
+
729
+ ## 0.53.1
730
+
731
+ The package ships its examples, and the README matches what the SDK does
732
+ (TT-2222). Generated from contract 154. No code change for callers.
733
+
734
+ ### Changed
735
+
736
+ - `examples/` is in the package. The README keeps the partner guide; the
737
+ repository's development and release notes moved to `CONTRIBUTING.md`,
738
+ which is not published.
739
+ - A withdrawal kept across a restart stores the whole `signWithdrawal`
740
+ record, `{ idempotencyKey, account, body }`; without `account`,
741
+ `sendWithdrawal` posts it and then throws "different terms".
742
+ - `waitForOperation` resolves at `REVERTED` and `EXPIRED_UNEXECUTED` as well
743
+ as `COMMITTED`; the README checks `status`.
744
+ - `onRfq` delivers each open RFQ once per subscription; another subscription
745
+ or a restart delivers the still-open ones again, and quoting again replaces
746
+ the earlier quote.
747
+ - `examples/browser-wallet.html` runs from a checkout of the SDK, not from an
748
+ installed copy; an app imports `browser-wallet.mjs` through its bundler.
749
+ - The `tpk_` server-key guards throw at runtime only; they cannot keep a key
750
+ out of a bundle.
751
+ - The README names staging's stream host, `wss://hip4-ws-staging.totalis.trade`.
752
+
753
+ ## 0.53.0
754
+
755
+ Markets say whether a Combo can take them and who deployed them; Esports is
756
+ its own category (TT-2196). Generated from contract 154.
757
+
758
+ - `Market.combo`: `{ state: "OPEN" }`, or `CLOSED` with `reason`
759
+ (`EXCLUDED`, `UNLISTED_DEPLOYER`, `OUTSIDE_WINDOW`) and `opens_at`, when an
760
+ `OUTSIDE_WINDOW` market joins Combos. RFQs refuse legs that are not `OPEN`.
761
+ - `Market.deployer`: `{ name, address }`; Hyperliquid's own markets have no
762
+ address, deployers Totalis does not list have no name and stay out of browse.
763
+ - `Category` adds `Esports`; `lol` moves there from Sports. Switches over
764
+ categories need the new case.
765
+
766
+ ## 0.52.0
767
+
768
+ `getProfitLeaderboard` reads the top 10 traders by profit, each as their
769
+ Portfolio Profit/Loss card shows it, with the same `range` and `kind` as
770
+ `getVolumeLeaderboard` and the same signed-in caller (TT-2157). Each trader
771
+ carries `profit` in atomic USDC. Generated from contract 153. Additive.
772
+
773
+ ## 0.51.1
774
+
775
+ Staging streams connect to their own host (TT-2204). Generated from contract
776
+ 152. No code change for callers.
777
+
778
+ ### Changed
779
+
780
+ - `publicStreamServers.staging` is `wss://hip4-ws-staging.totalis.trade`, so
781
+ `realtimeUrl("staging")` and `marketStreamUrl("staging")` open there. The API
782
+ host still serves both paths.
783
+
784
+ ## 0.51.0
785
+
786
+ Maker withdrawals from the dashboard or a bot (TT-2189). Generated from
787
+ contract 152. Additive.
788
+
789
+ - `GET /v1/makers/{maker_id}/withdrawal` and `maker.withdrawal()`: the
790
+ pending vault withdrawal (`amount`, `destination`, `ready_at`), whether
791
+ `executeMakerWithdraw` would succeed now, and its `blockers`
792
+ (`WITHDRAW_NOT_READY`, `VAULT_PAUSED`, `MAKER_SHORT`, `INSUFFICIENT_FREE`).
793
+ `pending` is null when none is live.
794
+ - `GET /v1/makers/{maker_id}/capital` now reports `MAKER_WITHDRAW` as
795
+ available: the amount a new request may ask for (`free_after_pending`), or
796
+ null with `MAKER_WITHDRAW_PENDING` while a request is live.
797
+ - The maker wallet still sends `requestWithdraw`, `executeWithdraw` and
798
+ `cancelWithdraw` from `maker.controller()` itself and pays the gas in HYPE.
799
+
800
+ ## 0.50.0
801
+
802
+ Breaking: `getVolumeLeaderboard` needs a signed-in participant session;
803
+ anonymous calls and API keys are refused. It returns up to 10 traders and
804
+ takes `kind`: `ALL` (the default), `SINGLES` for HyperCore fills alone or
805
+ `COMBOS` for Combo stakes alone, each with its own top 10, and the answer
806
+ names its `kind`. Each trader carries `avatar_seed`, so a client can draw the
807
+ same generated avatar as for `GET /v1/me`. Both are optional in the answer, so
808
+ servers before contract 151 may omit them. Generated from contract 151.
809
+
810
+ ## 0.49.0
811
+
812
+ Maker dashboard reads (TT-2188). Generated from contract 150. Additive.
813
+
814
+ ### Added
815
+
816
+ - `GET /v1/makers/{maker_id}/quote-history` (`listMakerQuoteHistory`): every
817
+ quote the maker published in `[from, through)`, newest first, with its
818
+ status (`OPEN`, `AWAITING_CONFIRMATION`, `ACCEPTED`, `FILLED`, `FAILED`,
819
+ `DECLINED`, `TIMED_OUT`, `CANCELLED`, `REPLACED`, `EXPIRED`, `NOT_SELECTED`,
820
+ `RFQ_CANCELLED`), stake, net stake, payout, maker risk or cash-out price,
821
+ submitted/accepted/resolved times and the period's `fill_rate`. Filters
822
+ `status` and `kind`; cursor paged.
823
+ - `GET /v1/makers/{maker_id}/exposure` (`getMakerExposure`): the maker's open
824
+ book by outcome: YES/NO, gross, net and worst-case exposure, netting
825
+ savings, and what awaits settlement.
826
+ - Positions carry `maker_pnl`, `maker_result` (`WON`, `LOST`, `EVEN`) and
827
+ `protocol_fees`; position lists filter on `maker_result`.
828
+ - Performance carries `history_from` (the earliest complete `from`),
829
+ `won_ticket_count`, `lost_ticket_count`, `even_ticket_count`,
830
+ `gross_winning_pnl` and `gross_losing_pnl`; each `series` point carries
831
+ `closed_ticket_count` and `net_trading_pnl_change` since the previous point.
832
+
833
+ ## 0.48.0
834
+
835
+ A stream closes `STREAM_REPLACED` when its owner opens a fifth live stream,
836
+ which replaces the owner's oldest (TT-2185). `TotalisStream` does not
837
+ reconnect; it emits a `StreamClosedError` with that reason, since reconnecting
838
+ would replace the owner's oldest stream in turn. Generated from contract 149,
839
+ whose error schema gains the reason.
840
+
841
+ ## 0.47.0
842
+
843
+ A maker is one wallet, its controller and its quote signer (TT-2181).
844
+ Breaking: `maker.controller()` / `controllerTransactions` no longer build
845
+ `setQuoteSigner`. Open a maker with `openMakerVaultTransaction(deployment,
846
+ wallet)` sent from that same wallet; nothing fills without its confirmation
847
+ signature, so stop confirming to stop filling. Generated from contract 148.
848
+
849
+ ## 0.46.0
850
+
851
+ `getMarketDefinitions` reads the native names and descriptions of every
852
+ question and outcome in the current catalog, with the network's reviewed
853
+ outcome templates. Generated from contract 148. Additive.
854
+
855
+ ## 0.45.0
856
+
857
+ Fund a Combo from HyperCore and resume every money flow after a reload or a
858
+ killed app (TT-2174). Generated from contract 147. Breaking: the native
859
+ HyperCore withdrawal routes (`/v1/hypercore/withdrawals*`) and their types are
860
+ gone; sign a `sendAsset` and submit it to Hyperliquid (or a relay) yourself,
861
+ since Hyperliquid's first answer settles it.
862
+
863
+ ### Added
864
+
865
+ - `signEntry({ quote, core?, sourceDex?, acceptanceId?, hypercoreNonce? })`:
866
+ signs a Combo entry as a plain JSON record. Funding is planned from current
867
+ balances: free vault cash, then the wallet, then a Core to HyperEVM bridge.
868
+ A vault balance the venue marks `STALE` or `UNKNOWN` throws `EntryError`
869
+ `BALANCE_UNKNOWN`; a wallet without a current read is authorized for the
870
+ whole shortfall and the venue checks it.
871
+ `core: null` means your Core read failed: an entry that needs the bridge
872
+ throws `EntryError` `BALANCE_UNKNOWN`. Without `core` it funds from the
873
+ wallet alone.
874
+ - `signCashout({ quote, acceptanceId? })`, and `sendAcceptance(signed,
875
+ { transport?, signal? })` / `recoverAcceptance(signed, { wait? })` for either
876
+ record. A refused bridge throws `EntryError` and posts nothing. Only
877
+ `sendAcceptance` sends the bridge, within the quote's life; recovery never
878
+ sends it or signs again, and only reads and fences the acceptance. An accept answer
879
+ that does not echo the record's acceptance, RFQ and quote IDs throws.
880
+ `recoverAcceptance(signed, { wait: false })` returns a `PENDING_CONFIRM`
881
+ acceptance at once instead of reading it again after the maker's deadline.
882
+ - `signCoreExit` / `sendCoreExit`, `signDeposit` / `sendDeposit` (sponsored
883
+ `POST /v1/me/deposits`), and `returnToCore` with `signReturnToCore` /
884
+ `sendReturnToCore`: deposit the wallet USDC, wait for it to commit, then exit
885
+ it with the free vault cash. External wallets only: an embedded wallet's
886
+ vault cash is already swept to HyperCore, so it throws there.
887
+ - `wallet_kind` (`EMBEDDED` or `EXTERNAL`) on `GET /v1/me`.
888
+ - `openPosition` takes `core`, `sourceDex`, `transport` and `onSigned`;
889
+ `cashOut` takes `onSigned`. Both return the record's IDs as before.
890
+ - Hyperliquid bridge helpers: `hyperliquidNetwork`, `bridgeAction`,
891
+ `sendAssetTypedData`, `signSendAsset`, `hypercoreSignature`,
892
+ `hypercoreNonce`, `usdcText`, `hyperliquidExchange`, `submitHypercore`,
893
+ `settleHypercore`, `classifyHypercoreAnswer`, `hyperevmUsdcBridge`,
894
+ `bridgeGasBuffer`.
895
+
896
+ ### Fixed
897
+
898
+ - A retried Core exit resends the same signed body under its exit ID. Before,
899
+ `exitToCore` signed again, which the venue refused as
900
+ `IDEMPOTENCY_KEY_REUSED`.
901
+
902
+ ### Changed
903
+
904
+ - `openPosition` and `cashOut` cancel their RFQ when signing fails, or when an
905
+ entry stops before its accept is posted.
906
+ - The lost-answer fence also holds when the cancel answers `NOT_FOUND`, and
907
+ holds on 409 only for `RFQ_NOT_CANCELLABLE`. After `STATE_CONFLICT` the RFQ
908
+ is still open, so a still-absent acceptance throws instead of ending
909
+ `NOT_ADMITTED`.
910
+
911
+ ## 0.44.0
912
+
913
+ New subcategory filters: Champions League (`ucl`) and Europa League (`uel`)
914
+ under Sports, HYPE (`hype`) under Crypto. Generated from contract 146.
915
+ Additive.
916
+
917
+ ## 0.43.0
918
+
919
+ High-frequency template rounds, like BTC every 15 minutes, read as recurring
920
+ rounds. Generated from contract 145. Additive.
921
+
922
+ ### Added
923
+
924
+ - `RecurringSeries.stream`: the deployer template stream (`stream_id`, `venue`,
925
+ `template`, `price_description`, `seconds`) behind a recurring round, or
926
+ `null` for a native recurring series.
927
+
928
+ ### Changed
929
+
930
+ - `recurring_round` on market detail, and the market recurring-round route,
931
+ also describe a qualified stream round. Its `target_price` is the template
932
+ threshold, and it settles YES only strictly above it. Such a market has no
933
+ `series_id`.
934
+
935
+ ## 0.42.0
936
+
937
+ The public volume leaderboard (TT-2157). Generated from contract 144.
938
+ Additive.
939
+
940
+ ### Added
941
+
942
+ - `GET /v1/leaderboard/volume` (`getVolumeLeaderboard`): up to 100 traders by
943
+ username and volume in 10^-8 USDC, for `range` `1W` (default) or `ALL`.
944
+
945
+ ## 0.41.0
946
+
947
+ Streams connect to a stream host apart from the API host (TT-2113). Still
948
+ contract 143. Additive, with one default change.
949
+
950
+ ### Added
951
+
952
+ - `streamBaseUrl` on `createTotalis`, `createMaker` and `TotalisStream`: the
953
+ WebSocket origin, apart from `baseUrl` (the REST origin).
954
+ - `publicStreamServers`, `streamServerUrl()`, `marketStreamUrl()` (joins
955
+ `fallback_stream` from `/v1/market-data/config` to the stream origin) and
956
+ `marketStreamProtocol` (`totalis.market.v2`).
957
+ - `realtimeUrl()` takes an optional third argument, `streamBaseUrl`.
958
+
959
+ ### Changed
960
+
961
+ - In production, streams connect to `wss://hip4-ws.totalis.trade` by default.
962
+ REST stays on `https://hip4-api.totalis.trade`, which still serves both stream
963
+ paths during the migration. A `baseUrl` without `streamBaseUrl` keeps
964
+ deriving the stream from `baseUrl`, as before; to go back to the API host,
965
+ pass `streamBaseUrl: "wss://hip4-api.totalis.trade"`.
966
+ - A `drain` frame's `retry_after_ms` is a floor: the stream reconnects after
967
+ between one and two times the hint, so the sockets one drain closes do not
968
+ all return at once.
969
+
970
+ ## 0.40.0
971
+
972
+ A first exit to a HyperCore account that does not exist yet can pay its
973
+ activation fee. Generated from contract 143.
974
+
975
+ ### Added
976
+
977
+ - `activation_fee_accepted` on the `POST /v1/core-exits` command and on every
978
+ `CoreExit`.
979
+ - The `CORE_ACCOUNT_ACTIVATION_REQUIRED` error code.
980
+ - `exitToCore({ activationFeeAccepted: true })` sends that consent.
981
+
982
+ ## 0.39.0
983
+
984
+ The Core funding float is dropped. Generated from contract 142. Breaking.
985
+
986
+ ### Removed
987
+
988
+ - The `PENDING_FUNDING` acceptance status. Only Core funding reached it.
989
+ - The retired `CORE_FUNDING_UNAVAILABLE`, `CORE_FUNDING_CONFLICT` and
990
+ `CORE_VAULT_RESERVATION` error codes.
991
+
992
+ ## 0.38.0
993
+
994
+ Core funding is retired. Generated from contract 141. Breaking.
995
+
996
+ ### Removed
997
+
998
+ - `GET /v1/me/core-fundings` (`activeCoreFundings`) and
999
+ `GET /v1/quotes/{quote_id}/acceptance/funding` (`getCoreFunding`), with the
1000
+ `core-funding` schemas.
1001
+ - `CORE` and `COMBINED` accept funding. `funding` on an accept is a `WALLET`
1002
+ authorization only; any other kind is `INVALID_REQUEST`. To spend Core USDC,
1003
+ bridge it to the wallet first.
1004
+ - The `CORE_FUNDING_UPDATED` stream event.
1005
+
1006
+ ### Changed
1007
+
1008
+ - `CORE_FUNDING_UNAVAILABLE`, `CORE_FUNDING_CONFLICT` and
1009
+ `CORE_VAULT_RESERVATION` stay registered but are retired; no route returns
1010
+ them.
1011
+
1012
+ ## 0.37.0
1013
+
1014
+ Usernames are optional, changeable, and name each account's /r/ link. Generated
1015
+ from contract 140. Additive, with one behaviour change.
1016
+
1017
+ ### Added
1018
+
1019
+ - `POST /v1/me/username` (`generateUsername`): an account that skipped choosing
1020
+ a username takes a generated one (`trader_` and six characters), returned as
1021
+ `GeneratedUsername`. An account with a username gets its own back. If every
1022
+ generated name it tries is taken, it answers `USERNAME_TAKEN`; try again.
1023
+
1024
+ ### Changed
1025
+
1026
+ - `PUT /v1/me/username` (`setUsername`) also changes an existing username, so it
1027
+ no longer answers `USERNAME_ALREADY_SET`. A Totalis campaign link, a reserved
1028
+ platform name or another account's earlier link name is `USERNAME_TAKEN`.
1029
+ - `getUsernameAvailability` reports a name Totalis keeps for its own links,
1030
+ such as `instagram`, as `TAKEN`.
1031
+ - `setUsername` and `generateUsername` answer `INVALID_REQUEST` to an
1032
+ `Idempotency-Key` stamped more than 5 minutes ahead of server time, since the
1033
+ keys put username changes in order.
1034
+
1035
+ ## 0.36.0
1036
+
1037
+ Profit/Loss series for Portfolio and backend-owned Chance and Value (TT-2004).
1038
+ Generated from contract 139. Additive.
1039
+
1040
+ ### Added
1041
+
1042
+ - Available market references carry nullable `chance`, `chance_basis`,
1043
+ `mark`, `last_trade` and `last_trade_at`. `chance` is the crowd view (mid
1044
+ within 10c, last trade inside a 10-50c spread, else null), and
1045
+ `chance_basis` says which (`MID` or `LAST_TRADE`); `mark` is what a held
1046
+ share is worth (chance, else best bid). Read them instead of deriving them
1047
+ from the book.
1048
+ - `GET /v1/me/pnl` (`getAccountPnl`): the cumulative trading P&L of the
1049
+ account Portfolio shows, for `range` `1D`, `1W`, `1M` (default) or `ALL`.
1050
+ `points` are `{at, pnl}` in atomic USDC, cumulative since `tracked_since`;
1051
+ a window's change is its last point minus its first. A `pnl` of `null` is
1052
+ unknown, never zero.
1053
+
1054
+ ## 0.35.0
1055
+
1056
+ Onboarding picks a username and an avatar (TT-1986). Generated from contract
1057
+ 138. Additive.
1058
+
1059
+ ### Added
1060
+
1061
+ - `getUsernameAvailability` (`GET /v1/me/username/availability?username=`)
1062
+ answers `UsernameAvailability` `{available, reason}`, where `reason` is
1063
+ `INVALID`, `NOT_ALLOWED`, `TAKEN` or `null`. The account's own username is
1064
+ available.
1065
+ - `setAvatar` (`PUT /v1/me/avatar`) with `AvatarRequest` `{avatar_seed}` sets
1066
+ the seed the account's generated avatar is drawn from.
1067
+
1068
+ ## 0.34.0
1069
+
1070
+ Followers survive a failed recovery read (TT-1902). Additive.
1071
+
1072
+ ### Fixed
1073
+
1074
+ - `withdraw`, `sendWithdrawal`, `waitForWithdrawal`, `waitForOperation`,
1075
+ `waitForCoreExit`, `reduceCollateral`, and the quotes read after a truncated
1076
+ snapshot no longer reject when a recovery read fails. Each recovery read is
1077
+ sent once, and the follower alone decides when to read again. A lost read
1078
+ (including a body cut off mid-response), a `BACKOFF` error, or a 500, 502,
1079
+ 503 or 504 without the venue's error envelope is read again, one read at a
1080
+ time, after the client's `retry` backoff and jitter, or the response's
1081
+ `Retry-After` capped at `maxDelayMs` when that is longer. A `Retry-After` of
1082
+ zero or a past date never skips the backoff. The backoff restarts after any
1083
+ successful read. A stream update or reconnect during the backoff, or during
1084
+ a read that then fails, reads at once; during a `Retry-After` wait it reads
1085
+ when the wait ends. Settling, the
1086
+ caller's abort and `close()` stop it and abort the read in flight. A `NEVER`
1087
+ or `REFRESH` refusal (such as 404 or 401), any other 5xx without the
1088
+ envelope (such as 501), or an error thrown by your own code (a chooser or
1089
+ token provider) still rejects.
1090
+ - `retry: false` turns off the request layer's resends; followers still read
1091
+ again, with the default backoff.
1092
+ - Resent requests keep the client's `mode`, `integrity`, `referrer`,
1093
+ `referrerPolicy` and `keepalive` instead of falling back to fetch defaults.
1094
+
1095
+ ### Added
1096
+
1097
+ - `follow(stream, read, done, wake, signal, retry)`: `read` receives an
1098
+ `AbortSignal` that aborts when the follow ends, and `retry` sets the
1099
+ recovery backoff.
1100
+
1101
+ ## 0.33.0
1102
+
1103
+ Wallet USDC deposits are back (TT-1788). Generated from contract 137. Additive.
1104
+
1105
+ ### Added
1106
+
1107
+ - `POST /v1/me/deposits` (`createDeposit`): a browser session moves USDC
1108
+ from its Privy embedded wallet into its Totalis balance. Send a
1109
+ `DepositEnvelope` whose command is the wallet's signed USDC
1110
+ `ReceiveWithAuthorization` with the vault as payee
1111
+ (`receiveWithAuthorizationTypedData`); Totalis relays it and pays the gas.
1112
+ The 202 `DepositAccepted` carries the queued `operation_id`. A deposit moves
1113
+ at least 1 USDC; an account gets at most 5 an hour (`RATE_LIMITED` with
1114
+ `Retry-After`). API keys cannot call it.
1115
+
1116
+ ## 0.32.1
1117
+
1118
+ Market stats cache lifetime (TT-1993). Generated from contract 136. No code
1119
+ change for callers.
1120
+
1121
+ ### Changed
1122
+
1123
+ - `GET /v1/market-stats` `Cache-Control` is `public, max-age=N` with N at most
1124
+ 30 and never past the snapshot's `valid_until`, or `no-store` within a second
1125
+ of expiry. Its generated header type is `string`.
1126
+
1127
+ ## 0.32.0
1128
+
1129
+ Vault v1 (TT-1959). Generated from contract 135. **Breaking** for makers that
1130
+ open or fund a vault with the SDK.
1131
+
1132
+ ### Changed
1133
+
1134
+ - `openMakerVaultTransaction(deployment, quoteSigner)`: the controller argument
1135
+ is gone. The sending wallet becomes the controller, a controller opens one
1136
+ maker, and the vault's `makerOf(controller)` returns its maker ID.
1137
+ - `controllerTransactions(deployment, makerId, controller)`: `deposit` encodes
1138
+ `depositMaker(makerId, controller, amount)`, which the vault refuses unless
1139
+ `controller` is the maker's current controller. `maker.controller()` reads
1140
+ it from `GET /v1/makers/{maker_id}/capital`.
1141
+ - `GET /v1/makers/{maker_id}/funding-transaction` returns the three-argument
1142
+ `depositMaker` call bound to the projected controller, or 404 for a maker
1143
+ the projection has not seen.
1144
+ - Position and cash-out RFQ legs allow up to 100 (`maxItems`), the vault's leg
1145
+ limit. Entry RFQs and quotes keep their 50-leg request limit.
1146
+ - `AWAITING_SETTLEMENT` also covers a position whose payout, with every
1147
+ unresolved leg counted as a win, already rounds down to zero.
1148
+ - New error code `COLLATERAL_REDUCTION_UNAVAILABLE` (503, `BACKOFF`):
1149
+ `POST /v1/makers/{maker_id}/collateral-reductions` refuses it, without
1150
+ queueing a job, while the vault has no attestor. Vault v1 starts that way.
1151
+
1152
+ ## 0.31.0
1153
+
1154
+ Every account has a generated avatar (TT-1975). Generated from contract 134.
1155
+ Additive.
1156
+
1157
+ ### Added
1158
+
1159
+ - `VenueIdentity.avatar_seed`: a random UUID fixed when the account is created,
1160
+ for drawing the account's avatar. Optional, so servers before contract 134
1161
+ may omit it.
1162
+
1163
+ ## 0.30.0
1164
+
1165
+ Partner admission needs the wallet's consent (TT-1688). Generated from contract
1166
+ 133. **Breaking** for partner servers.
1167
+
1168
+ ### Changed
1169
+
1170
+ - `createPartnerServer(...).admitWallet(address, consent)`: the consent is
1171
+ required. A consent for another partner, wallet, environment or chain, or an
1172
+ expired one, is `INVALID_SIGNATURE`.
1173
+
1174
+ ### Added
1175
+
1176
+ - `signAdmissionConsent({ signer, partner, environment, chainId })`: in the
1177
+ partner's frontend, the wallet signs that the partner may open its account.
1178
+ `admissionConsentMessage` is the exact message.
1179
+
1180
+ ## 0.29.0
1181
+
1182
+ Funding helpers for external wallets (TT-1685). Still contract 132. Additive.
1183
+
1184
+ ### Added
1185
+
1186
+ - `exitToCore({ amount, purpose? })`: the wallet signs an Exit to the CoreExit
1187
+ router and the exit is sent once under its exit ID. `waitForCoreExit(exitId)`
1188
+ follows it on the stream until it is credited on HyperCore, and rejects
1189
+ `RECOVERED`, `FAILED` or `ABANDONED`. External wallets have no background
1190
+ sweep, so this is how their cash reaches HyperCore before a native order.
1191
+ - `directDepositCalls(amount)`: the approve and `depositUser(account, amount)`
1192
+ transactions for a self-paid HyperEVM deposit.
1193
+
1194
+ ## 0.28.0
1195
+
1196
+ Wallet sign-in and partner credentials for external wallets (TT-1685). Still
1197
+ contract 132. Additive.
1198
+
1199
+ ### Added
1200
+
1201
+ - `./wallet-session`: `signInWithWallet` asks for a challenge, checks it is
1202
+ the Totalis sign-in for this origin, wallet and request, has the wallet sign
1203
+ it, and returns the session. `signOutWallet` ends it.
1204
+ `checkSignInChallenge` is the check on its own.
1205
+ - `./partner`: `createPartnerServer({ serverKey }).admitWallet(address)`, for a
1206
+ partner's server. It refuses to run in a browser.
1207
+ - `partnerKey` on every client: the publishable `tpb_` key, sent as
1208
+ `X-Totalis-Partner`. A `tpk_` server key is refused.
1209
+ - `examples/partner-frontend.mjs` and `examples/partner-server.mjs`.
1210
+
1211
+ ## 0.27.0
1212
+
1213
+ Partners admit wallets (TT-1678). Generated from contract 132. Additive.
1214
+
1215
+ ### Added
1216
+
1217
+ - `admitPartnerWallet` (`POST /v1/partner/wallet-admissions`): a partner's
1218
+ server, with its secret `tpk_` key, admits a wallet so the wallet's next
1219
+ `createWalletSession` creates its account. Server-side only; never put the
1220
+ key in a browser.
1221
+
1222
+ ## 0.26.0
1223
+
1224
+ Browse contract 4 groups IPO market-cap ladders and sports games (TT-1853).
1225
+ Generated from contract 131. Additive for contracts 2 and 3.
1226
+
1227
+ ### Added
1228
+
1229
+ - `./browse`: contract `"4"` (query parameter, header, `totalis.market.browse.v4`
1230
+ stream). Contract 4 cards add `DiscoveryGameItem` (`kind: "GAME"`, `game:<key>`
1231
+ ID, `game` with `sport`, `scheduled_start`, `participants` and the
1232
+ `winner_outcome_ids`, `spread_outcome_ids`, `total_outcome_ids` that partition
1233
+ its markets) and SERIES cards whose `series` is an `IpoMarketCapSeries`
1234
+ (`template: "COMPANY_IPO_MARKET_CAP"`, `company`, `listing_deadline`).
1235
+ - `getMarket`: optional `contract` query parameter. With `"4"` the detail adds
1236
+ `game` (`MarketGame` or null) and sets `series_id` for IPO ladder members.
1237
+
1238
+ ### Changed
1239
+
1240
+ - `Series.series` and `DiscoverySeriesItem.series` are `SeriesDescriptor`, a
1241
+ union discriminated by `template`: `PriceSeries` or `IpoMarketCapSeries`.
1242
+ Contracts 2 and 3 never return an `IpoMarketCapSeries`; narrow on
1243
+ `template` before reading `underlying`.
1244
+
1245
+ ## 0.25.0
1246
+
1247
+ Externally owned wallets can sign in (TT-1676). Generated from contract 130.
1248
+ Additive.
1249
+
1250
+ ### Added
1251
+
1252
+ - `createWalletChallenge` (`POST /v1/auth/wallet-challenges`) returns the
1253
+ EIP-4361 message for a wallet to sign with `personal_sign`. It answers
1254
+ `WALLET_CONTRACT_UNSUPPORTED` for an address with contract code.
1255
+ - `createWalletSession` (`POST /v1/auth/wallet-sessions`) exchanges the
1256
+ signature for a `Bearer` session for the wallet's existing account. The
1257
+ session lasts at most 30 days and ends after 7 days without an API request.
1258
+ A wallet that is not an account's own wallet gets `ACCESS_REQUIRED`.
1259
+ - `endWalletSession` (`DELETE /v1/auth/wallet-sessions/current`) logs that
1260
+ session out.
1261
+ - Error code `WALLET_CONTRACT_UNSUPPORTED`.
1262
+
1263
+ ## 0.24.0
1264
+
1265
+ Accounts have a public username, set once (TT-1953). Generated from contract
1266
+ 129. Additive.
1267
+
1268
+ ### Added
1269
+
1270
+ - `setUsername` (`PUT /v1/me/username`) with `UsernameRequest`, and the errors
1271
+ `USERNAME_NOT_ALLOWED`, `USERNAME_TAKEN` and `USERNAME_ALREADY_SET`.
1272
+ - `VenueIdentity.username`: the account's username, or `null` until it is set.
1273
+ Optional, so servers before contract 129 may omit it.
1274
+
1275
+ ## 0.23.0
1276
+
1277
+ A price series links its sibling expiries (TT-1907). Generated from contract
1278
+ 128. Additive.
1279
+
1280
+ ### Added
1281
+
1282
+ - `Series.siblings`: the other current series on the same network, template and
1283
+ underlying, as `SeriesSibling` (`series_id`, `expiry`) by expiry ascending, up
1284
+ to 64. Optional, so servers before contract 128 may omit it.
1285
+
1286
+ ## 0.22.0
1287
+
1288
+ Settlement credits have their own read, and no read writes. Needs contract 127.
1289
+ Additive.
1290
+
1291
+ ### Added
1292
+
1293
+ - `getHypercoreSettlementCredits` (`GET /v1/hypercore/settlement-credits`,
1294
+ browser session only): the account's retained USDC settlement credits from
1295
+ storage, with no Hyperliquid read. Same mainnet and linked-account checks as
1296
+ `getHypercorePortfolio`.
1297
+
1298
+ ### Changed
1299
+
1300
+ - `getAcceptance` only reads. An unanswered acceptance that has lapsed reads as
1301
+ `TIMED_OUT` or `CANCELLED` before the venue stores it.
1302
+ - `getHypercorePortfolio` and `getHypercoreWithdrawal` only read. Settlement
1303
+ credits come from the background observer, so a new settlement appears once
1304
+ the observer has passed it; a withdrawal advances when the background
1305
+ reconciler resolves it.
1306
+
1307
+ ## 0.21.1
1308
+ Settlement credits name the market they settled (TT-1929). Generated from
1309
+ contract 126; the types are unchanged.
1310
+ ### Changed
1311
+ - `Activity.fill` is set on `CREDIT` rows: the outcome and side that settled,
1312
+ `direction` `SELL`, `size` the shares settled and `price` what one share of
1313
+ that side paid (`1` for a win, `0` for a loss, in between for a fractional
1314
+ settlement). `size` times `price` is the payout before the fee effect.
1315
+ ## 0.21.0
1316
+
1317
+ A session admits its maker from its linked wallet, with no signature. Needs
1318
+ contract 125, which drops the signed registration. Breaking only for callers of
1319
+ the removed operations.
1320
+
1321
+ ### Added
1322
+
1323
+ - `admitOwnMaker` (`POST /v1/me/maker`, browser session only): admits the
1324
+ lowest maker whose controller and quote signer are both the account's
1325
+ qualified linked wallet and returns the `GET /v1/me/maker` body (`OwnMaker`).
1326
+ No body and no `Idempotency-Key`; a repeat returns the current ownership.
1327
+ `404 NOT_FOUND` until such a maker is indexed, `409 STATE_CONFLICT` when the
1328
+ wallet already has a profile for a different maker.
1329
+
1330
+ ### Removed
1331
+
1332
+ - `createMakerOnboardingChallenge`, `registerMaker` and `getMakerRegistration`
1333
+ (`POST /v1/maker-onboarding/challenges`, `POST
1334
+ /v1/maker-onboarding/registrations` and `GET
1335
+ /v1/maker-onboarding/registrations/{maker_id}`), with the `ChallengeEnvelope`,
1336
+ `Challenge`, `ProofEnvelope` and `Profile` maker-access schemas. `OwnerProof`
1337
+ stays: API key issuance uses it.
1338
+ - `MakerAccess.expires_at`, which was always `null`: owner access does not
1339
+ expire.
1340
+
1341
+ ## 0.20.0
1342
+
1343
+ Maker dashboard access comes only from owning the maker. Needs contract 124,
1344
+ which drops the legacy dashboard grants. Breaking only for callers of the
1345
+ removed operations.
1346
+
1347
+ ### Removed
1348
+
1349
+ - `createMakerAccessChallenge`, `consumeMakerAccessProof`,
1350
+ `grantMakerMembership` and `revokeMakerMembership` (`POST
1351
+ /v1/makers/{maker_id}/access/challenges`, `POST .../access/proofs`, `PUT` and
1352
+ `DELETE /v1/makers/{maker_id}/members/{participant_id}`), with their
1353
+ `MembershipRequest` and `AccessChallenge` schemas and the unused `MakerList`.
1354
+ - `MANAGE_ACCESS` from `Permission`.
1355
+
1356
+ ### Changed
1357
+
1358
+ - `MakerAccess.expires_at` is always `null`: owner access does not expire.
1359
+ - The README and `examples/node-bot.mjs` sign with your exported Totalis
1360
+ wallet key, `TOTALIS_WALLET_KEY` (was `QUOTE_SIGNER_KEY`).
1361
+
1362
+ ## 0.19.0
1363
+
1364
+ Activity effects carry their asset, fills carry their trade and positions
1365
+ carry what the owner paid (TT-1875, TT-1862). Needs contract 123.
1366
+
1367
+ ### Added
1368
+
1369
+ - `Effect.asset` (`Asset`: `asset_id`, `symbol`, `decimals`). `delta` is in
1370
+ that asset's atomic units: HyperEVM USDC has 6 decimals, HyperCore USDC and
1371
+ HYPE have 8. Never assume 6.
1372
+ - `Activity.fill`: outcome, side, direction, size, price, oid and tid on
1373
+ `FILL` and `CONVERSION` rows; null on every other kind.
1374
+ - `Position.acquisition_cost`: the gross stake with the entry fee for the
1375
+ opener, or the latest transfer price for a buyer; null when the chain
1376
+ history can't establish it.
1377
+
1378
+ ### Changed
1379
+
1380
+ - Workflow activities (a pending or failed Combo, cash-out or withdrawal) set
1381
+ `occurred_at` to the time the request was made, which later revisions keep.
1382
+ - A HyperCore send with a HYPE fee and a spot to perp transfer without a nonce
1383
+ now appear instead of being held back.
1384
+
1385
+ ## 0.18.0
1386
+
1387
+ A quote's `kind` names its terms (TT-1916): `ENTRY`, `SELL_BACK` or
1388
+ `TRANSFER`, replacing `CASHOUT`. Needs contract 122, which serves only the new
1389
+ shape. Breaking. Terms and signed EIP-712 structs are unchanged.
1390
+
1391
+ ### Changed
1392
+
1393
+ - `Quote` (list quotes, the account snapshot's `quotes`, `QUOTE_CREATED`) is
1394
+ the union of `EntryQuote`, `SellBackQuote` and `TransferQuote`; each carries
1395
+ exactly its own terms (`entry`, `sell_back` or `transfer`), so narrowing on
1396
+ `kind` types the terms.
1397
+ - `MakerAcceptance` (`QUOTE_ACCEPTED`, the maker snapshot's `acceptances`,
1398
+ `GET /v1/makers/{maker_id}/acceptances`) is the same three-way union.
1399
+ - `CashoutBid` is `SellBackQuote | TransferQuote`; `SellBackQuote` and
1400
+ `TransferQuote` are exported from the root.
1401
+ - An RFQ's `kind` stays `ENTRY` or `CASHOUT`.
1402
+
1403
+ ## 0.17.0
1404
+
1405
+ Compact chart closes and a preflight-free browse contract. Needs contract 121.
1406
+
1407
+ ### Added
1408
+
1409
+ - `GET /v1/markets/{outcome_id}/reference-closes`
1410
+ (`getMarketReferenceCloses`): `REFERENCE_PRICE_OHLC` history reduced to
1411
+ closes. `runs` holds `CloseRun` tuples `[minute, close, minutes]`, with
1412
+ `minute` in Unix seconds; `anchor` is `{ minute, close }`. The parameters,
1413
+ source, scale, `closed_before` and cursor match history, and `limit`
1414
+ counts minutes, not runs.
1415
+ - `./browse`: a `contract` query parameter (`"2"` or `"3"`) on discovery,
1416
+ search and taxonomy. It negotiates like `X-Totalis-Browse-Contract` but adds
1417
+ no custom header, so browsers skip the CORS preflight.
1418
+
1419
+ ### Changed
1420
+
1421
+ - `./browse`: `contract` is required and `X-Totalis-Browse-Contract` is
1422
+ optional, so every typed request negotiates and matches its typed response.
1423
+ A header-only caller adds `query: { contract }`; the header may stay if it
1424
+ matches. The server still negotiates on the header alone.
1425
+
1426
+ ## 0.16.0
1427
+
1428
+ Everything the caller owns lives under `/v1/me` (TT-1786). Needs contract
1429
+ 120, which serves only the new paths. Breaking. Signed EIP-712 structs are
1430
+ unchanged.
1431
+
1432
+ ### Changed
1433
+
1434
+ - `POST /v1/positions/{position_id}/cashout` is now
1435
+ `POST /v1/me/positions/{position_id}/cashout` (`createCashout`), which
1436
+ `cashOut` calls.
1437
+ - `GET /v1/operations/{operation_id}` is now
1438
+ `GET /v1/me/operations/{operation_id}` (`getOperation`), which
1439
+ `waitForOperation` rereads, for personal and maker keys alike.
1440
+ - `POST /v1/withdrawals` is now `POST /v1/me/withdrawals` (`createWithdrawal`),
1441
+ which `sendWithdrawal` and `withdraw` call.
1442
+ - `GET /v1/withdrawals/{withdrawal_id}` is now
1443
+ `GET /v1/me/withdrawals/{withdrawal_id}` (`getWithdrawal`), the recovery read
1444
+ behind `withdraw` and `waitForWithdrawal`.
1445
+ - The `Operation` and `Withdrawal` types are unchanged; only the paths they
1446
+ are keyed on moved.
1447
+
1448
+ ## 0.15.0
1449
+
1450
+ Browse contract 3 groups standalone price-threshold markets into price series
1451
+ (TT-1905). Needs contract 119.
1452
+
1453
+ ### Added
1454
+
1455
+ - `./browse`: `X-Totalis-Browse-Contract: "3"`, the `DiscoverySeriesItem`
1456
+ card (`kind: "SERIES"`, `series: {template, underlying, expiry}`, two or more
1457
+ member `markets`) and `series:` item IDs in cards and browse updates.
1458
+ Contract 2 never returns them.
1459
+ - `GET /v1/series/{series_id}` (`getSeries`): one price series with every
1460
+ active member plus the most recently listed inactive members, up to 256.
1461
+ Members are `SeriesMarket`s, whose `native_question_id` is always `null`.
1462
+ - `series_id` on `MarketDetail`: the series key of a standalone binaryPrice or
1463
+ priceTouch market, else `null`.
1464
+ - `totalis.market.browse.v3` stream updates carry contract `"3"` and may name
1465
+ `series:` cards.
1466
+
1467
+ ## 0.14.0
1468
+
1469
+ The API speaks prediction-market vocabulary (TT-1904): quotes, acceptances
1470
+ and positions, keyed by `quote_id` and `position_id`, and a v2 stream. Needs
1471
+ contract 118, which serves only the new surface. Breaking.
1472
+
1473
+ ### Changed
1474
+
1475
+ - Taker (`createTotalis`): `placeBet` is `openPosition`, `watchBook` is
1476
+ `watchQuotes`, and `release()` is `deployment()` (`GET /v1/deployment`).
1477
+ `openPosition` returns `{ rfqId, acceptanceId, quoteId, positionId, entry,
1478
+ status, operationId, outcome }`; an entry position is named by its quote, so
1479
+ `positionId` is `quoteId`. `cashOut({ positionId })` creates the cash-out RFQ
1480
+ with `POST /v1/positions/{position_id}/cashout` (`POST /v1/rfqs` is
1481
+ entry-only) and returns `{ rfqId, acceptanceId, quoteId, positionId, status,
1482
+ operationId, outcome }`.
1483
+ - Accepting is `POST /v1/quotes/{quote_id}/accept` with `{ taker_signature,
1484
+ funding? }`. Its required `Idempotency-Key` is the acceptance ID, a UUIDv7
1485
+ made before the first send and reused for every resend. A lost accept is
1486
+ recovered from `GET /v1/quotes/{quote_id}/acceptance`; `NotAdmitted` is
1487
+ `{ status: "NOT_ADMITTED", quote_id, rfq_id }`.
1488
+ - Acceptance status: `PENDING_CONFIRM`, `PENDING_FUNDING` (was `CONFIRMED`),
1489
+ `ACCEPTED` (was `COMMITTED`), `FILLED` and `FAILED` (from the operation),
1490
+ `DECLINED`, `TIMED_OUT`, and `CANCELLED` (was `WITHDRAWN`).
1491
+ - Maker (`createMaker`): `withdraw(rfqId, digest)` is `cancelQuote(quoteId)`
1492
+ (`DELETE /v1/quotes/{quote_id}`, answering `{ status }`), `onConfirmation` is
1493
+ `onAcceptance`, and `release()` is `deployment()`. `quote()` posts
1494
+ `{ quote_id, entry }` and `bid()` `{ quote_id, sell_back | transfer }` to
1495
+ `POST /v1/rfqs/{rfq_id}/quotes`; both return `quoteId`. The answer is
1496
+ `POST /v1/quotes/{quote_id}/confirm` with a `decision` and no
1497
+ Idempotency-Key: the quote keys it. Truncated acceptances are paged from
1498
+ `GET /v1/makers/{maker_id}/acceptances`.
1499
+ - Legs are `{ outcome_id: "<decimal>", side: "YES" | "NO" }` everywhere, as
1500
+ markets and positions name them. The typed-data builders encode them as the
1501
+ signed `uint32`/`uint8`, and read `position_id` into the signed `ticketId`;
1502
+ digests and signatures are unchanged.
1503
+ - Entry RFQs carry `taker` and `stake` (were `taker_address` and
1504
+ `stake_amount`); cash-out RFQs and cash-out terms carry `position_id` (was
1505
+ `ticket_id`). A quote's entry terms are `entry` (was `quote`).
1506
+ - Lifecycle fields are `status` (were `state`) on RFQs, operations,
1507
+ withdrawals, collateral reductions (`operation_status`) and stream payloads.
1508
+ RFQs are `OPEN`, `ACCEPTED` (was `SELECTED`), `EXPIRED`, `CANCELLED` (the
1509
+ stream's `EXPIRED` and REST's `CANCELLED` now agree) or `FAILED` (was
1510
+ `CLOSED`); an operation's `DURABLE` is `QUEUED`.
1511
+ - The stream is `totalis.realtime.v2`. `StreamOptions.topic` is `subscription`:
1512
+ `{ type: "account", open_rfqs? }` or `{ type: "maker", maker_id }`. The client
1513
+ sends `{ method: "subscribe", subscription }` and every server frame is
1514
+ `{ channel, data }`; `RealtimeHello` and `RealtimeReady` are
1515
+ `RealtimeSubscribe` and `RealtimeSubscriptionResponse`. An event carries
1516
+ `cursor` (was `stream`); a snapshot carries `truncated` (was
1517
+ `continuations`) and the account's `quotes` (was `book_quotes`) and
1518
+ `acceptances`.
1519
+ - Event names: `QUOTE_CREATED` / `QUOTE_REMOVED` (were `BOOK_QUOTE_*`),
1520
+ `QUOTE_ACCEPTED` (was `CONFIRMATION_REQUESTED`), `RFQ_CREATED` (was
1521
+ `ENTRY_RFQ_OPENED` and `CASHOUT_RFQ_OPENED`), `RFQ_ACCEPTED` (was
1522
+ `RFQ_SELECTION_DURABLE`), `RFQ_FAILED` (was `RFQ_CLOSED`),
1523
+ `OPERATION_UPDATED` (was `EXECUTION_REPORT` and `WITHDRAWAL_REPORT`),
1524
+ `VAULT_BALANCE_CHANGED` (was `BALANCE_CHANGED`), `WALLET_FUNDING_UPDATED`,
1525
+ `POSITION_*` (were `TICKET_*`, now `{ position_id, block_number, log_index }`
1526
+ without the stored ticket status) and `MAKER_CAPITAL_UPDATED`.
1527
+ - A wallet funding carries `kind: "WALLET"`.
1528
+ - Types: `BookQuote`, `Confirmation` and `Release` are `Quote`, `Acceptance`
1529
+ and `Deployment`; `MakerConfirmationRequest` and `MakerConfirmation` are
1530
+ `MakerAcceptance` and `Acceptance`; `TotalisRelease` and `UsdcRelease` are
1531
+ `TotalisDeployment` and `UsdcDeployment`.
1532
+ - API key scopes `ticket:accept` and `ticket:cashout` are `quote:accept` and
1533
+ `position:cashout`.
1534
+
1535
+ ### Removed
1536
+
1537
+ - `clientInstanceId` on the stream, and the v1 `session.hello` protocol.
1538
+
1539
+ ## 0.13.0
1540
+
1541
+ `GET /v1/vault` no longer reports whether financial actions are enabled
1542
+ (TT-1900). Needs contract 117. Breaking.
1543
+
1544
+ ### Removed
1545
+
1546
+ - `financial_actions_enabled` on `Release`. The venue still refuses
1547
+ balance-affecting commands while a release is disabled; the command fails
1548
+ with `FINANCIAL_ACTIONS_DISABLED`, so read that error rather than the release.
1549
+
1550
+ ## 0.12.0
1551
+
1552
+ Commands, the stream and identity carry only what a reader uses (TT-1866).
1553
+ Needs contract 116. Breaking.
1554
+
1555
+ ### Changed
1556
+
1557
+ - A command body is the command itself: the five POST commands
1558
+ (`createRfq`, `publishBookQuote`, `beginConfirmation`, `finishConfirmation`,
1559
+ `createWithdrawal`) no longer wrap it in `{schema_version, request_id,
1560
+ sent_at, command}`; `envelope()` now wraps only the commands that still carry
1561
+ it (core exits, HyperCore withdrawals and maker onboarding).
1562
+ `error.request_id` is the response's `X-Request-ID`. The body types are `CreateRfqCommand`, `BookQuoteCommand`,
1563
+ `ConfirmationAcceptanceCommand`, `MakerConfirmationCommand` and
1564
+ `WithdrawalCommand` (were the `…Envelope` types).
1565
+ - The venue fills the addresses the credential implies from its one embedded
1566
+ wallet, and the signed typed data still names that wallet: `createRfq` sends
1567
+ no `taker_address`, a wallet funding (`WalletFunding`, was the collateral
1568
+ envelope's `command`) no `account` or `from`, and `createWithdrawal` no
1569
+ `account` and a `vault_withdrawal` without `account` and `to`.
1570
+ `signWithdrawal` returns `{ idempotencyKey, account, body }`.
1571
+ - A stream event is `{stream, event_id, event_type, occurred_at, payload}`.
1572
+ `ENTRY_RFQ_OPENED` carries the whole open entry RFQ; `onRfq` delivers it, and
1573
+ a cash-out RFQ, as an `Rfq` with `state: "OPEN"` and reads nothing. A
1574
+ replayed opening is skipped once its collection has ended, and otherwise
1575
+ re-read and delivered only while the RFQ is still open.
1576
+ - `GET /v1/me` returns `{ account_id, status, wallet }`.
1577
+ - The attempt routes' `Idempotency-Key` header is optional; `attempt_id` is
1578
+ the key. The SDK still sends it.
1579
+
1580
+ ### Removed
1581
+
1582
+ - `quote_digest` and `taker_signature` inside a wallet funding (copies of the
1583
+ accept's own).
1584
+ - `chain_id` and `vault_address` on book offers (the list, the snapshot's
1585
+ `book_quotes` and `BOOK_QUOTE_PUBLISHED`), on the publication checkpoint,
1586
+ and `max_frame_bytes` on `session.ready`: read the deployment from
1587
+ `/v1/vault`.
1588
+ - `schema_version`, `resource_kind` and `resource_id` on stream events; the
1589
+ `rfqDetails` stream option and the event frame's `rfq`.
1590
+ - `state` and `terminal_reason` on `ENTRY_RFQ_OPENED` and `CASHOUT_RFQ_OPENED`
1591
+ payloads (the event type says it is OPEN).
1592
+ - The retired `ENTRY_QUOTE_DISPLAYED`, `CASHOUT_BID_DISPLAYED` and
1593
+ `*_REMOVED_FROM_DISPLAY` events and their payload types.
1594
+ - `state` and `operation_id` on `MakerConfirmationRequest`.
1595
+ - `LegacyTerminalCashoutRfq`.
1596
+ - `wallets`, `owner`, `signer` and `privy_did` on `GET /v1/me`.
1597
+
1598
+ ## 0.11.0
1599
+
1600
+ Account and maker reads carry amounts, not envelopes (TT-1866). Needs contract
1601
+ 115. Breaking.
1602
+
1603
+ ### Changed
1604
+
1605
+ - Every account-read amount (`Metric`, `UnsignedMetric`) is an atomic USDC
1606
+ string, or `null` when unavailable. One `context: { as_of, status }` per
1607
+ response replaces each amount's asset, authority, sources, method, time,
1608
+ status and reason.
1609
+ - `context` is `{ as_of, status }`. Paging binds to one snapshot through the
1610
+ opaque `next_cursor`; there is no `snapshot_id` to compare.
1611
+ - An activity lists `transaction_hashes` (was `evidence`), and each effect is
1612
+ `{ bucket, delta, classification }`.
1613
+ - `GET /v1/me/balances` returns the one balance at the top level (was
1614
+ `balances[0]`), without `product` or `unit`. A `Checkpoint` has no
1615
+ `chain_id`. The `ProductBalanceList` type is `Balance`.
1616
+ - The activity, position and list types are shared by account and maker
1617
+ reads: `ActivityList`, `ActivityDetail` and `PositionList` (were the
1618
+ `Account…` and `Maker…` variants).
1619
+
1620
+ ### Removed
1621
+
1622
+ - `contract_version` and `scope` on account and maker reads.
1623
+ - `funding_id` and `transfer_id` on an activity, and the `asset` activity
1624
+ filter.
1625
+ - `initial_exposure` (it is `signed_payout - net_stake`) and
1626
+ `claim_evidence_ids` on a position; `total_net_stake`,
1627
+ `total_initial_exposure` and `activity_url` on position reads.
1628
+ - `allocated_wallet_cash` on maker capital; `asset`, `bucket`, `funding_id`,
1629
+ `expires_at` and evidence IDs on its reservations.
1630
+ - `unrealized_pnl`, `return_on_capital` and `gas_by_asset` on maker
1631
+ performance, which were never available.
1632
+ - `lens_address` on `Release`.
1633
+
1634
+ ## 0.10.0
1635
+
1636
+ Market data carries only what a reader uses (TT-1866). Needs contract 114.
1637
+ Breaking.
1638
+
1639
+ ### Changed
1640
+
1641
+ - `Market.dates` is always present, and also carries `scheduled_event_at`,
1642
+ `observation_ends_at` and `market_class`. It is null only when the market has
1643
+ neither reviewed timing nor a market class.
1644
+ - `Question` and `MarketDetail` carry `catalog_generation`; a `MarketDetail`'s
1645
+ `question.markets` omits the requested market, which is `market`.
1646
+ - `MarketHistory` carries `side`, `scale` and `volume_scale` once; each bar is
1647
+ `{minute, open, high, low, close, volume, trade_count}`. A scale change starts
1648
+ a new page. `include_gaps` defaults to `false`.
1649
+ - `MarketDetail.stats` is `{volume_24h, open_interest}` in atomic USDC.
1650
+ - `MarketDetail.metadata` is `{content: {title, rules}, parent, sides: [{side,
1651
+ label}]}`.
1652
+
1653
+ ### Removed
1654
+
1655
+ - From `Market`: `deadline`, `quote_asset`, `catalog_generation`, `source`,
1656
+ `taxonomy_state`, `taxonomy_source` and `taxonomy_version`. From its sides:
1657
+ `asset_id`, and the reference's `source`, `feed_generation` and
1658
+ `source_time`; `quality` names the feed class.
1659
+ - The same provenance fields from `Question` and discovery items, and the
1660
+ `CatalogSource`, `TaxonomySource`, `TaxonomyState` and `TaxonomyVersion`
1661
+ types.
1662
+ - `MarketDetail.feed_generation`, and `price_semantics`, `volume_semantics`,
1663
+ `interval` and `fill_policy` from `MarketHistory`, which follow from
1664
+ `series_type`.
1665
+
1666
+ The market stream's catalog entries and references keep their shape
1667
+ (`FeedReference`).
1668
+
1669
+ ## 0.9.0
1670
+
1671
+ Partners call only what trading needs (TT-1841). Needs contract 112. Breaking.
1672
+
1673
+ ### Changed
1674
+
1675
+ - `withdraw`, `signWithdrawal` and `sendWithdrawal` send
1676
+ `POST /v1/withdrawals` (was `/v1/totalis-withdrawals`), and follow
1677
+ `WITHDRAWAL_UPDATED` on a `WITHDRAWAL` (was
1678
+ `TOTALIS_WITHDRAWAL_CONTINUATION_UPDATED` on a `CONTINUATION`), reading
1679
+ `GET /v1/withdrawals/{withdrawal_id}` only after a reconnect.
1680
+ - A withdrawal is the `Withdrawal` type (was `TotalisWithdrawal`) and its ID is
1681
+ `withdrawal_id` (was `continuation_id`); `onStarted` and `waitForWithdrawal`
1682
+ take that ID.
1683
+
1684
+ ### Removed
1685
+
1686
+ - `deposit` and `POST /v1/deposits`: `placeBet` already funds a vault
1687
+ shortfall from the wallet in the accept. The `DepositAccepted` type.
1688
+ - `withdrawFromVault` and the vault-only `POST /v1/withdrawals`: `withdraw`
1689
+ moves any vault shortfall on its way out. The `OperationAccepted` type.
1690
+ - `settleTicket`, `claimTicket` and the ticket routes (`/claims`,
1691
+ `/settlements`, `/transfers`): Totalis settles and claims every decided
1692
+ ticket itself. `transferTypedData` and the plain `Transfer` type.
1693
+ - `POST /v1/operations/{operation_id}/self-funded-transaction`; a maker's
1694
+ `reduceCollateral` keeps its own route.
1695
+ - The `ticket:settle` and `ticket:transfer` key scopes, and `operations:submit`
1696
+ for personal keys.
1697
+
1698
+ ## 0.8.0
1699
+
1700
+ A maker key reads its own account through `/v1/me`, and the maker stream is its
1701
+ only replay (TT-1841). Needs contract 111. Breaking.
1702
+
1703
+ ### Changed
1704
+
1705
+ - `TotalisStream` resumes a persisted `cursor` on the stream itself: the hello
1706
+ carries it and the venue replays the retained events after it, or resets to
1707
+ a snapshot. `createMaker` no longer reads events over HTTP first. Every
1708
+ `event` listener now receives the frame.
1709
+ - The maker snapshot has no `quotes` class, and its `operations` continuation is
1710
+ `GET /v1/me/operations`.
1711
+ - A maker key reads `GET /v1/me/positions[/{ticket_id}]`,
1712
+ `GET /v1/me/activity[/{activity_id}]`, `GET /v1/me/operations` and
1713
+ `GET /v1/operations/{operation_id}` for its maker.
1714
+
1715
+ ### Removed
1716
+
1717
+ - The `replay` stream option and `replayPages`.
1718
+ - Calls to `GET /v1/makers/{maker_id}/events`, `/snapshot`, `/offers`,
1719
+ `/operations[/{operation_id}]`, `GET /v1/me/makers` and
1720
+ `GET /v1/hypercore/history`, which are gone from the venue.
1721
+ - Issuing the `maker:access:read` key scope (its reads are app-session only).
1722
+
1723
+ ## 0.7.0
1724
+
1725
+ Market data is list, detail and history (TT-1841). Needs contract 110. Breaking.
1726
+
1727
+ ### Changed
1728
+
1729
+ - `GET /v1/markets/{outcome_id}` (`MarketDetail`) also carries `metadata`
1730
+ (the product metadata at the market's catalog generation),
1731
+ `recurring_round` (null outside a recurring series) and `stats` (the
1732
+ market's 24h volume and open interest, null before a snapshot).
1733
+
1734
+ ### Removed
1735
+
1736
+ - `GET /v1/markets/{outcome_id}/metadata` (read `metadata` on the market
1737
+ detail) and `GET /v1/questions` (read `question` on the market detail),
1738
+ with the `STALE_CATALOG` error code.
1739
+
1740
+ ## 0.6.0
1741
+
1742
+ An external withdrawal is one request (TT-1775). Needs contract 109. Breaking.
1743
+
1744
+ ### Changed
1745
+
1746
+ - `withdraw` signs the Exit for any wallet shortfall and the USDC
1747
+ `TransferWithAuthorization` payout up front and sends them in one
1748
+ `POST /v1/totalis-withdrawals` (`payout_authorization`). The payout's nonce is
1749
+ `payoutNonce(release, account, idempotencyKey)`, so the signature is bound to
1750
+ that request. It resolves at `PAYOUT_COMMITTED` from
1751
+ `TOTALIS_WITHDRAWAL_CONTINUATION_UPDATED`, which now carries the whole
1752
+ withdrawal, and reads `GET /v1/totalis-withdrawals/{id}` only after a
1753
+ reconnect. `FAILED` throws; the USDC is then still in the vault or the
1754
+ wallet.
1755
+ - `transferWithAuthorizationTypedData(release, payout)` takes
1756
+ `{ from, to, value, valid_after, valid_before, nonce }`.
1757
+ - A withdrawal is `VAULT_WITHDRAWAL_QUEUED`, `PAYOUT_SUBMITTED`,
1758
+ `PAYOUT_COMMITTED` or `FAILED`, and carries `payout_operation_id`,
1759
+ `payout_transaction_hash` and `updated_at`.
1760
+
1761
+ ### Added
1762
+
1763
+ - `signWithdrawal` and `sendWithdrawal`, to store a signed withdrawal before
1764
+ sending it, and `waitForWithdrawal` to follow one after a restart.
1765
+ - `payoutNonce` and the `PayoutAuthorization` type in `./typed-data`.
1766
+
1767
+ ### Removed
1768
+
1769
+ - `resumeWithdrawal` (use `waitForWithdrawal`), the `WalletTransfer` type, and
1770
+ calls to `/payout-claim` and `/payout-submission`.
1771
+
1772
+ ## 0.5.0
1773
+
1774
+ A maker that starts or reconnects with more than 100 pending confirmation
1775
+ requests now sees all of them (TT-1838). Needs contract 107.
1776
+
1777
+ ### Changed
1778
+
1779
+ - `onConfirmation` pages `GET /v1/makers/{maker_id}/confirmations` when the
1780
+ snapshot names it as the `confirmations` continuation, and handles every
1781
+ request it returns once, like the snapshot's and the stream's. A failed read
1782
+ reaches `onError` without a request, so its `request` parameter is now
1783
+ optional.
1784
+
1785
+ ## 0.4.0
1786
+
1787
+ Fewer RFQ routes: the taker keeps the book from the account stream, and entry
1788
+ and cash-out share one accept (TT-1835). Needs contract 106. Breaking.
1789
+
1790
+ ### Changed
1791
+
1792
+ - The taker's book comes from the account stream: the snapshot's
1793
+ `book_quotes`, then `BOOK_QUOTE_PUBLISHED` and `BOOK_QUOTE_REMOVED`.
1794
+ `GET /v1/rfqs/{rfq_id}/book-quotes` is read only for an RFQ followed after a
1795
+ snapshot that truncated `book_quotes`. `BookQuote` is the one offer shape
1796
+ for both kinds; choosers take `Chooser<EntryQuote>` (`bestQuote`) or
1797
+ `Chooser<CashoutBid>` (`bestBid`) with the venue clock. Expiry sends no
1798
+ event, so an offer leaves the book (and `watchBook` re-renders) once it has
1799
+ no more signed life than the venue needs to begin on it: 2 s for a quote,
1800
+ 22 s for a bid.
1801
+ - `placeBet` and `cashOut` use one accept,
1802
+ `POST /v1/rfqs/{rfq_id}/attempts/{attempt_id}`. `cashOut` has the owner sign
1803
+ the bid's `SellBack` or `CashoutTransfer` before the accept and returns
1804
+ `{ rfqId, attemptId, quoteDigest, state, operationId, outcome }`: `COMMITTED`
1805
+ with `operationId` means the sell-back or transfer is queued. `bid_digest` is
1806
+ now `quote_digest`.
1807
+ - A lost accept the venue never received is recovered by reading the attempt,
1808
+ cancelling the RFQ (204 or 409) and reading again; still absent is
1809
+ `{ state: "NOT_ADMITTED" }`. `ABANDONED` is gone.
1810
+ - `createMaker`: `bid` publishes on `POST /v1/rfqs/{rfq_id}/book-quotes` with
1811
+ `{ quote_digest, sell_back | transfer }` and returns `quoteDigest`.
1812
+ `onConfirmation` answers `CONFIRMATION_REQUESTED` (live, or replayed from
1813
+ `GET /v1/makers/{maker_id}/events` on resume) and the snapshot's
1814
+ `confirmations`, including requests delivered before it was attached; its
1815
+ `onError` always receives the request. `MakerConfirmationRequest` is the
1816
+ event's payload type.
1817
+
1818
+ ### Removed
1819
+
1820
+ - `watchCashoutBook` (`watchBook` renders quotes and bids) and the
1821
+ `CashoutConfirmation` type.
1822
+ - Calls to `/cashout-book`, `/cashout-attempts`, `/attempts/{id}/abandon`,
1823
+ `/tickets/{ticket_id}/sell-back` and `GET /v1/makers/{maker_id}/confirmations`.
1824
+
1825
+ ### Added
1826
+
1827
+ - `stream.serverNow()`: the venue clock from `session.ready` and publication
1828
+ checkpoints.
1829
+ - `EntryQuote` and `NotAdmitted` types.
1830
+
1831
+ ## 0.3.1
1832
+
1833
+ ### Fixed
1834
+
1835
+ - `withdraw` / `resumeWithdrawal` no longer wait forever after the vault
1836
+ top-up or the payout commits. The venue advances a withdrawal only when it is
1837
+ read, so the flow now also re-reads on the `WITHDRAWAL_REPORT` or
1838
+ `EXECUTION_REPORT` of the withdrawal's own operation, and on
1839
+ `WALLET_BALANCE_CHANGED` for its wallet (found by TT-1778).
1840
+
1841
+ ## 0.3.0
1842
+
1843
+ Helpers for the flows the SDK-first docs could only show as raw API calls, and
1844
+ fees and USDC read from `GET /v1/vault` (TT-1832). Needs contract 105.
1845
+
1846
+ ### Added
1847
+
1848
+ - `createTotalis`: `withdrawFromVault` (direct `POST /v1/withdrawals` with a
1849
+ signed Exit), `settleTicket` and `claimTicket`.
1850
+ - `createMaker`: `controller()` builds the maker's vault transactions
1851
+ (`setQuoteSigner`, `approveUsdc`, `deposit`, `requestWithdraw`,
1852
+ `executeWithdraw`, `cancelWithdraw`, `resetDiscount`) from the canonical ABI
1853
+ for the controller wallet to send; `reduceCollateral` follows a collateral
1854
+ reduction and can submit its attestation through the self-funded route.
1855
+ - `/maker` also exports `controllerTransactions`,
1856
+ `openMakerVaultTransaction`, `encodeCall` and `TransactionCall`.
1857
+
1858
+ ### Changed
1859
+
1860
+ - `createMaker` no longer takes `fees`: quotes carry the vault's current
1861
+ `fee_bps` and `taker_fee_bps`, read from `GET /v1/vault` for every quote so a
1862
+ governance change applies at once, and `quote` throws until the venue
1863
+ publishes them.
1864
+ - `usdcDomain(release)`, `receiveWithAuthorizationTypedData(release, …)` and
1865
+ `transferWithAuthorizationTypedData(release, transfer, window)` take USDC and
1866
+ its signing domain from the release; `usdcTokens` is removed.
1867
+
1868
+ ## 0.2.0
1869
+
1870
+ The SDK core on the current API (TT-1784).
1871
+
1872
+ ### Added
1873
+
1874
+ - `createTotalis`: `placeBet` (RFQ, book from the stream, one synchronous
1875
+ accept, wallet funding of a vault shortfall), `cashOut`, `deposit`,
1876
+ `withdraw` / `resumeWithdrawal` (sponsored Totalis withdrawal),
1877
+ `waitForOperation`, `watchBook` / `watchCashoutBook`, `issueApiKey` /
1878
+ `rotateApiKey`.
1879
+ - `createMaker` (`/maker`): `quote`, `bid`, `withdraw`, `confirm`,
1880
+ `onConfirmation`, `onRfq`, with HTTP replay from a persisted cursor.
1881
+ - `TotalisStream` (`/realtime`): snapshot, replay, deduplication, reconnect
1882
+ with backoff, close-reason retry handling and stale-socket detection.
1883
+ - A request layer: every client resends the same bytes and `Idempotency-Key`
1884
+ after network failures and `BACKOFF` errors, honouring `Retry-After`;
1885
+ `unwrap` throws `ApiError`; `NetworkError` (with `resend()` for flow commands); `sendOnce`; `uuidv7`; `envelope`.
1886
+ - `pages`, `items` and `replayPages` over the TT-1771 list shape.
1887
+ - `toTotalisSigner` (`/signer`) for viem accounts and wallet clients,
1888
+ EIP-1193 providers and ethers signers.
1889
+ - Typed data: `hashTypedData`, `hashDomain`, `receiveWithAuthorizationTypedData`,
1890
+ `depositNonce`, `transferWithAuthorizationTypedData`, `usdcDomain`,
1891
+ `canonicalSignature`, `issueKeyMessage`, `parseIssueKeyMessage`.
1892
+ - `ApiClientOptions`: `baseUrl`, `retry`, and `accessToken` as a function.
1893
+ - Node bot and browser-wallet examples.
1894
+
1895
+ ### Changed
1896
+
1897
+ - `signTotalis` returns a canonical signature (v in {27, 28}).
1898
+ - `./errors` also exports `ApiError` and `NetworkError`.
1899
+
1900
+ ## 0.1.0
1901
+
1902
+ Generated client, maker, operator, realtime, browse and account-read types;
1903
+ API-key client; typed data for vault signatures.