@metamask-previews/perps-controller 19.0.0-preview-8cc0f94 → 19.0.0-preview-cbae429b5

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 (114) hide show
  1. package/CHANGELOG.md +3 -114
  2. package/README.md +1 -586
  3. package/dist/PerpsController-method-action-types.d.ts +14 -133
  4. package/dist/PerpsController-method-action-types.d.ts.map +1 -1
  5. package/dist/PerpsController-method-action-types.js.map +1 -1
  6. package/dist/PerpsController.d.ts +14 -111
  7. package/dist/PerpsController.d.ts.map +1 -1
  8. package/dist/PerpsController.js +42 -507
  9. package/dist/PerpsController.js.map +1 -1
  10. package/dist/aggregation/SubscriptionMultiplexer.d.ts +3 -7
  11. package/dist/aggregation/SubscriptionMultiplexer.d.ts.map +1 -1
  12. package/dist/aggregation/SubscriptionMultiplexer.js +2 -4
  13. package/dist/aggregation/SubscriptionMultiplexer.js.map +1 -1
  14. package/dist/constants/hyperLiquidConfig.d.ts +1 -15
  15. package/dist/constants/hyperLiquidConfig.d.ts.map +1 -1
  16. package/dist/constants/hyperLiquidConfig.js +2 -16
  17. package/dist/constants/hyperLiquidConfig.js.map +1 -1
  18. package/dist/constants/lighterConfig.d.ts +1 -61
  19. package/dist/constants/lighterConfig.d.ts.map +1 -1
  20. package/dist/constants/lighterConfig.js +1 -62
  21. package/dist/constants/lighterConfig.js.map +1 -1
  22. package/dist/index.d.ts +3 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/perpsErrorCodes.d.ts +0 -1
  26. package/dist/perpsErrorCodes.d.ts.map +1 -1
  27. package/dist/perpsErrorCodes.js +0 -1
  28. package/dist/perpsErrorCodes.js.map +1 -1
  29. package/dist/providers/AggregatedPerpsProvider.d.ts +4 -69
  30. package/dist/providers/AggregatedPerpsProvider.d.ts.map +1 -1
  31. package/dist/providers/AggregatedPerpsProvider.js +7 -176
  32. package/dist/providers/AggregatedPerpsProvider.js.map +1 -1
  33. package/dist/providers/HyperLiquidProvider.d.ts +5 -5
  34. package/dist/providers/HyperLiquidProvider.d.ts.map +1 -1
  35. package/dist/providers/HyperLiquidProvider.js +145 -416
  36. package/dist/providers/HyperLiquidProvider.js.map +1 -1
  37. package/dist/providers/LighterProvider.d.ts +57 -149
  38. package/dist/providers/LighterProvider.d.ts.map +1 -1
  39. package/dist/providers/LighterProvider.js +1119 -8262
  40. package/dist/providers/LighterProvider.js.map +1 -1
  41. package/dist/services/HyperLiquidClientService.d.ts +2 -3
  42. package/dist/services/HyperLiquidClientService.d.ts.map +1 -1
  43. package/dist/services/HyperLiquidClientService.js +3 -14
  44. package/dist/services/HyperLiquidClientService.js.map +1 -1
  45. package/dist/services/LighterClientService.d.ts +2 -30
  46. package/dist/services/LighterClientService.d.ts.map +1 -1
  47. package/dist/services/LighterClientService.js +10 -151
  48. package/dist/services/LighterClientService.js.map +1 -1
  49. package/dist/services/TradingService.d.ts.map +1 -1
  50. package/dist/services/TradingService.js +2 -23
  51. package/dist/services/TradingService.js.map +1 -1
  52. package/dist/types/index.d.ts +21 -402
  53. package/dist/types/index.d.ts.map +1 -1
  54. package/dist/types/index.js.map +1 -1
  55. package/dist/types/lighter-types.d.ts +1 -94
  56. package/dist/types/lighter-types.d.ts.map +1 -1
  57. package/dist/types/lighter-types.js.map +1 -1
  58. package/dist/utils/lighterAdapter.d.ts +0 -7
  59. package/dist/utils/lighterAdapter.d.ts.map +1 -1
  60. package/dist/utils/lighterAdapter.js +4 -4
  61. package/dist/utils/lighterAdapter.js.map +1 -1
  62. package/dist/utils/subscriptionFeeWaiver.d.ts +6 -7
  63. package/dist/utils/subscriptionFeeWaiver.d.ts.map +1 -1
  64. package/dist/utils/subscriptionFeeWaiver.js +6 -12
  65. package/dist/utils/subscriptionFeeWaiver.js.map +1 -1
  66. package/package.json +1 -1
  67. package/dist/services/LighterChaseService.d.ts +0 -578
  68. package/dist/services/LighterChaseService.d.ts.map +0 -1
  69. package/dist/services/LighterChaseService.js +0 -1117
  70. package/dist/services/LighterChaseService.js.map +0 -1
  71. package/dist/services/LighterTwapService.d.ts +0 -288
  72. package/dist/services/LighterTwapService.d.ts.map +0 -1
  73. package/dist/services/LighterTwapService.js +0 -511
  74. package/dist/services/LighterTwapService.js.map +0 -1
  75. package/dist/services/lighterDispatchIdentity.d.ts +0 -28
  76. package/dist/services/lighterDispatchIdentity.d.ts.map +0 -1
  77. package/dist/services/lighterDispatchIdentity.js +0 -43
  78. package/dist/services/lighterDispatchIdentity.js.map +0 -1
  79. package/dist/utils/guardedHyperLiquidClient.d.ts +0 -13
  80. package/dist/utils/guardedHyperLiquidClient.d.ts.map +0 -1
  81. package/dist/utils/guardedHyperLiquidClient.js +0 -38
  82. package/dist/utils/guardedHyperLiquidClient.js.map +0 -1
  83. package/dist/utils/lighterAttachedOrders.d.ts +0 -53
  84. package/dist/utils/lighterAttachedOrders.d.ts.map +0 -1
  85. package/dist/utils/lighterAttachedOrders.js +0 -212
  86. package/dist/utils/lighterAttachedOrders.js.map +0 -1
  87. package/dist/utils/lighterChase.d.ts +0 -75
  88. package/dist/utils/lighterChase.d.ts.map +0 -1
  89. package/dist/utils/lighterChase.js +0 -207
  90. package/dist/utils/lighterChase.js.map +0 -1
  91. package/dist/utils/lighterLosslessJson.d.ts +0 -11
  92. package/dist/utils/lighterLosslessJson.d.ts.map +0 -1
  93. package/dist/utils/lighterLosslessJson.js +0 -136
  94. package/dist/utils/lighterLosslessJson.js.map +0 -1
  95. package/dist/utils/lighterNativeEdit.d.ts +0 -238
  96. package/dist/utils/lighterNativeEdit.d.ts.map +0 -1
  97. package/dist/utils/lighterNativeEdit.js +0 -573
  98. package/dist/utils/lighterNativeEdit.js.map +0 -1
  99. package/dist/utils/lighterScaleOrders.d.ts +0 -106
  100. package/dist/utils/lighterScaleOrders.d.ts.map +0 -1
  101. package/dist/utils/lighterScaleOrders.js +0 -496
  102. package/dist/utils/lighterScaleOrders.js.map +0 -1
  103. package/dist/utils/lighterTwap.d.ts +0 -42
  104. package/dist/utils/lighterTwap.d.ts.map +0 -1
  105. package/dist/utils/lighterTwap.js +0 -79
  106. package/dist/utils/lighterTwap.js.map +0 -1
  107. package/dist/utils/lighterTwapReconciliation.d.ts +0 -35
  108. package/dist/utils/lighterTwapReconciliation.d.ts.map +0 -1
  109. package/dist/utils/lighterTwapReconciliation.js +0 -237
  110. package/dist/utils/lighterTwapReconciliation.js.map +0 -1
  111. package/dist/utils/positionProtection.d.ts +0 -12
  112. package/dist/utils/positionProtection.d.ts.map +0 -1
  113. package/dist/utils/positionProtection.js +0 -29
  114. package/dist/utils/positionProtection.js.map +0 -1
package/README.md CHANGED
@@ -66,27 +66,6 @@ an asset with an open position, resting order, or active native TWAP schedule,
66
66
  including schedules whose first slice has not filled. Orders in the same mode may
67
67
  increase or reduce the existing position.
68
68
 
69
- ## Explicit Lighter margin mode and collateral adjustments
70
-
71
- Lighter accepts explicit `cross` or `isolated` mode with a positive integer
72
- `leverage` on ordinary native orders and attached protection orders for active
73
- perpetual markets. Existing positions and resting, pending or position-tied
74
- orders prevent changing their market mode. Omitted mode preserves existing
75
- selection behavior. Scale and strategy probes continue to reject explicit mode.
76
-
77
- A mode selection must have an exactly identified executed transaction and a
78
- fresh account row showing the selected mode before dependent exposure is signed
79
- or dispatched. Transport acceptance alone does not establish execution.
80
-
81
- `updateMargin` requires an open isolated position and exact micro-USDC precision.
82
- Positive amounts are bounded by fresh available account collateral; negative
83
- amounts require authoritative allocated position margin. The original position
84
- identity and bounds are checked again before signing and final dispatch. The
85
- venue still enforces its own position-risk limits. Success requires exact
86
- transaction execution. Unresolved collateral and mode transactions remain
87
- blocked across restart, nonce advance and expiry until exact terminal proof;
88
- refresh recovered outcomes before explicitly acknowledging them.
89
-
90
69
  ## Signing without a `KeyringController`
91
70
 
92
71
  By default the controller signs through the `KeyringController:*` messenger
@@ -133,570 +112,6 @@ a free slot instead: the Lighter API answers "api key not found" for
133
112
  `GET /api/v1/apikeys?account_index=<account>&api_key_index=<slot>` when the
134
113
  slot is free.
135
114
 
136
- ## Lighter standalone trigger orders
137
-
138
- Lighter supports `stop_market`, `stop_limit`, `take_profit_market` and
139
- `take_profit_limit` through `placeOrder`. Supply a positive `triggerPrice` on
140
- the market's fixed price grid; limit execution also requires `price`. Market
141
- execution applies the caller's slippage protection to the trigger level, and
142
- USD sizing uses that level rather than the current market price. Protection
143
- defaults to 5% when neither `maxSlippageBps` nor `slippage` is supplied. Both trigger
144
- and execution prices must fit the venue's wire range.
145
-
146
- Leave `timeInForce` unset: pending triggers use the signer's default 28-day expiry,
147
- with IOC execution for trigger markets and GTT execution for trigger limits.
148
- `reduceOnly` retains the requested quantity. Below-minimum trigger limits are
149
- refused even when they would currently close the full position; a position can
150
- grow before activation. Attached TP/SL and strategy fields are unsupported on
151
- these standalone orders.
152
-
153
- Position TP/SL replacement and removal recognize Core-created protection by
154
- durable client/venue IDs, even after position growth, shrinkage, provider restart
155
- or trading-key recovery into another slot. IDs are recorded before dispatch in
156
- wallet/account/network/market-scoped storage and retained through uncertain
157
- settlement. Resolved cancellations and exact terminal history prune them;
158
- storage read errors or corrupt records fail closed before protection changes.
159
- Ownership bookkeeping reads at most one recent history page. New records include
160
- the exact client's signed absolute order expiry. When the active book no longer
161
- contains an ID, it can be reclaimed after that expiry plus 30 seconds of clock
162
- slack, even if terminal history is buried or unavailable. Transaction expiry
163
- does not prove an order has expired. Active IDs and unexpired missing IDs remain
164
- owned; legacy records with unknown order expiry need exact terminal history.
165
- Bookkeeping never deep-scans history. Ownership is capped at 256 entries per
166
- wallet/account/network/market. If verified cleanup cannot make room, new
167
- protection creation refuses before dispatch rather than forgetting uncertain
168
- orders. Known live orders can still be explicitly cancelled. Journal
169
- settlement remains strict: an observed accepted submission cannot become
170
- never-landed because of a later missing lookup, and expiry proofs are recomputed
171
- on each reconciliation rather than persisted across restarts.
172
-
173
- Legacy unrecorded reduce-only trigger-market orders on the closing side with
174
- exactly the current position quantity retain their position-protection contract,
175
- including standalone orders placed through `placeOrder`. Protection created
176
- before this ownership upgrade, or after its local records are lost, has no
177
- recorded ownership IDs. If that position has resized, the old trigger remains
178
- legacy and may need explicit cancellation before new protection is established.
179
- Classification reads the current position inside the write lock. Known IOC and GTT wire intents can be
180
- replaced or removed; an unknown time-in-force refuses the change. Independent
181
- partial triggers and trigger limits are preserved. Use explicit cancellation to
182
- remove those orders. Quantity does not determine ownership of Core-created TP/SL.
183
-
184
- Managed Lighter TP/SL removal does not require an integerizable position quantity
185
- after preflight: exact recorded protection IDs can still be cancelled when an
186
- authoritative positions array shows no position, zero size or a size below the
187
- tick. Account-read failures or malformed position envelopes still refuse the
188
- operation. Unrecorded legacy protection still requires a valid live quantity and
189
- side for classification; replacement retains its size and side checks. A supplied
190
- `expectedPosition` must still match for managed removal, including after signing.
191
-
192
- `getOrderCapabilities` reports these types only for active, known perpetual markets.
193
- Capabilities and trigger preflight refresh public metadata and fail closed on
194
- read errors instead of relying on a session's old active-market snapshot.
195
- `MarketInfo.priceDecimals` exposes Lighter's fixed price grid for callers
196
- deriving thresholds. Missing precision is unknown, not a zero-decimal grid.
197
-
198
- ## Explicit dispatch reconciliation
199
-
200
- `reviewRecoveryVenue({ providerId })` reads fresh authoritative positions and orders
201
- for one provider, wallet, network and venue account. A ready response carries that
202
- scope and `reviewedAt`; transport, identity, authentication or metadata failures
203
- reject instead of returning an empty account. The read can sign an authentication
204
- token with a matching locally retained registered key. It never registers a key,
205
- allocates a venue slot, signs a financial transaction, starts protection recovery,
206
- or acknowledges or clears an obligation. Missing local read authority requires
207
- reconnecting a matching key. Aggregated callers must name the owning provider;
208
- unsupported providers return `status: 'unsupported'`.
209
-
210
- A manual protection row may include an opaque `recoveryId`. After review, an
211
- explicit `resolveRecoveryProtection({ providerId, recoveryId, symbol,
212
- expectedPosition, takeProfitPrice, stopLossPrice })` selects that exact obligation
213
- and requests new protection (omit both prices for removal). Preserve the ID
214
- verbatim. Lighter reconciles pending original-slot attempts by their exact venue
215
- identity before using a matching current registered key; the original private key
216
- is not required when this evidence is authoritative. The successor only replaces
217
- orders owned by the selected obligation. Its durable source relationship survives
218
- response loss and restart; failed or ambiguous settlement leaves recovery visible.
219
- The result distinguishes `settled`, `unresolved`, and `unsupported`. This is an
220
- explicit financial operation and must never run as part of review or rendering.
221
-
222
- `getRecoveredDispatches()` and `getPendingManualRecoveries()` list local recovery
223
- state. Confirmed account absence and known Premium accounts retain their local rows without signer setup
224
- or venue reconciliation; a wallet with no recorded obligations returns an empty
225
- inventory. Premium trading remains unsupported. Transport failures, corrupt or
226
- unavailable storage, wrong-wallet accounts and unknown account types still reject.
227
- Verified accounts are indexed before venue mutation so nonce-only obligations
228
- remain discoverable after restart even if the venue reports account absence.
229
- Existing protection indices also preserve older account identities. Legacy
230
- nonce-only obligations without an account or protection index become discoverable
231
- when the venue account returns; they are never deleted or reset during absence.
232
- Account capacity is bounded by `LIGHTER_RECOVERY_ACCOUNT_INDEX_LIMIT`, exported through
233
- `constants` and `constants/lighterConfig`.
234
-
235
- Call `reconcileRecoveredDispatches()` only when the user requests a status check.
236
- This non-financial operation reads venue evidence and updates local ledgers.
237
- It does not initialize a signer, register a key, sign, submit, cancel, acknowledge
238
- or retry an intent. Lighter checks owner-null dispatches across all trading slots;
239
- TP/SL-owned entries and their journals remain pending for their separate recovery
240
- flow. Existing quarantines do not prevent checking other unresolved entries.
241
-
242
- Replace the displayed list with the returned list, including its opaque IDs.
243
- Pending rows and all local-only absent or Premium rows have
244
- `acknowledgeable: false`. Acknowledgment requires a supported current account.
245
- A pending row disappearing can mean its exact transaction was proven absent,
246
- not successful execution. Unknown outcomes remain unknown. Acknowledgment still requires explicit user review and
247
- never grants permission to resubmit an ambiguous intent. Providers without this
248
- capability return their local listing, or an empty list if they have no recovery
249
- state. Aggregation rejects when any provider fails; consumers should retain their
250
- last known rows alongside that error.
251
-
252
- ## Lighter fixed partial position protection
253
-
254
- `updatePositionTPSL` accepts a positive `takeProfitSize` or `stopLossSize` for
255
- one trigger, or both sizes for an equal-quantity OCO pair. Explicit quantities
256
- normalize downward on the market size grid without increasing the request.
257
- Values below one tick or above the exact current position are rejected. With
258
- the default native OCO linkage, unequal normalized quantities or only one supplied
259
- size are rejected before mutation. Omitting both sizes retains the existing full-position snapshot
260
- behavior. Explicit sizes never become the venue's dynamic zero-quantity
261
- sentinel.
262
-
263
- Partial replacement cancels only managed or explicitly selected protection, then
264
- proves exact cancellations before creating the replacement. Unrelated independent orders
265
- remain untouched. This leaves a protection gap if creation fails. The durable
266
- operation records the original fixed quantities and client IDs before
267
- cancellation; ambiguous creation is reconciled without replay.
268
-
269
- A proven-unsent operation releases its journal and permits fresh intent. Listing
270
- keeps unsent journals selectable until a fresh update retires them.
271
- Current-key journals with attempted transactions may appear while their
272
- operation is still running; wait for the issuing operation to finish before
273
- choosing recovery.
274
-
275
- After a dispatched cancellation or interrupted creation, recovery never attaches
276
- the saved quantity automatically. Lighter does not expose an immutable position
277
- lifecycle ID, so even an identical-looking position could have been closed and
278
- reopened. Ordinary retries cannot change or dispatch the stored intent. Inspect
279
- the exact recovery and call `resolveRecoveryProtection` with its recovery ID and
280
- a fresh explicit intent for the current position. The capability metadata
281
- reports this boundary, snapshot coverage, and supported pair linkages.
282
- Hyperliquid continues to report independent fixed partial triggers and dynamic
283
- whole-position coverage through its existing implementation.
284
-
285
- Explicit `partialPairLinkage: 'independent'` supports equal or unequal TP/SL
286
- quantities, including an omitted sibling captured from the full current position.
287
- At least one size and both prices are required. The default remains native equal
288
- OCO; explicit OCO is never converted to independent orders. `supportedPairs`
289
- reports the available choices while `pair` retains the provider default.
290
- Independent triggers are submitted TP then SL with separate durable identities.
291
- Uncertainty, rejection, a fired first leg or changed position stops the sibling.
292
- Failures retain accepted coverage and expose observed role-bound
293
- `positionProtection` receipts; saved requests are never automatically replayed.
294
- An omitted `requestedSize` in a receipt means captured full-position coverage.
295
- Venue activation and sibling cancellation are not implied by independent linkage.
296
-
297
- ## Native Lighter attached orders
298
-
299
- `placeOrder` accepts a market or limit parent with `takeProfitPrice`,
300
- `stopLossPrice`, or both. Omit attached child sizes. `tpslLinkage` defaults to
301
- `order`. The native OTO or OTOCO transaction contains the opening parent and
302
- zero-size, opposite-side, reduce-only trigger-market children. An explicit
303
- child quantity, position linkage, reduce-only parent, caller-supplied client
304
- ID, or invalid price or size grid is refused before signer setup. IOC and
305
- resting GTC limit parents are supported. The caller's slippage also bounds
306
- child market execution prices.
307
-
308
- `OrderResult.attachedOrderGroup` separates signed client IDs from observed
309
- venue IDs and returns an opaque group handle. `getAttachedOrderGroups` lists
310
- durable local identities across restarts and trading-key changes without signer
311
- setup. Confirmed absent or known Premium accounts retain local groups through
312
- the wallet-scoped recovery account index; listing never acknowledges or replays
313
- them. `reviewAttachedOrderGroups` uses an existing registered local key for
314
- read-only venue authentication, then matches exact signed IDs against bounded
315
- active and bounded older inactive history for missing legs. A preparation-time
316
- cutoff stops reads before the group could have existed. The page/row budget
317
- returns `historyStatus: bounded` with unknown missing legs rather than failing
318
- reviews of other groups. Older journals without a preparation time retain the
319
- explicit budget. Missing orders or linkage stay unknown. A successful
320
- submission reports acceptance, not activation, a fill, or protected quantity.
321
- If a pending `placeAttached:` dispatch blocks writes, call
322
- `reviewAttachedOrderGroups` to refresh exact venue evidence, then
323
- `reconcileRecoveredDispatches` and acknowledge only a resolved outcome. A
324
- pending, non-acknowledgeable dispatch cannot be cleared by acknowledgment alone.
325
-
326
- Pass the exact `groupId` as `cancelOrder.orderId`, with its symbol and
327
- provider, to cancel the owned parent and children. Cancellation rereads exact
328
- IDs after each leg, preserves unrelated triggers and reports success only when
329
- all legs are terminal. Missing identities retain the group for later explicit
330
- review. The group handle never cancels a position or creates replacement
331
- protection. Attached children are excluded from ordinary position TP/SL
332
- replacement/removal.
333
-
334
- Unsigned intent is persisted before signing and transaction identity before
335
- dispatch. Ambiguous acceptance remains quarantined across restart and key
336
- migration. There is no automatic financial replay or attachment to a later
337
- position. Explicitly cancel a prepared group before submitting fresh intent;
338
- uncertain dispatches also require the existing exact-transaction reconciliation
339
- and acknowledgment flow. Exact failure observed by review remains durable until
340
- nonce-ledger retirement succeeds, including retries after storage failure. When
341
- the exact hash stays absent but the nonce advanced, explicit review can
342
- transfer fresh complete exact-leg observations into an acknowledgeable
343
- succeeded outcome. Saved IDs alone never authorize this transfer. The group
344
- remains owned; acknowledgment permits later intentional writes and exact
345
- cancellation without replay. Reconciliation persists exact failed, expired or
346
- nonce-consumed non-acceptance before retiring the nonce evidence; explicit
347
- group cancellation can then abandon that intent without a cancellation
348
- signature or replay of the grouped order. Signer setup and authentication still
349
- apply. Nonce advance before signed expiry remains ambiguous. Abandonment
350
- rereads exact transaction and bounded order history, and refuses recorded or
351
- freshly correlated legs. Missing history alone never proves non-acceptance. Up
352
- to 64 groups are retained per account. Only canceled groups or `completed`
353
- groups with all legs exactly correlated as terminal can be evicted. Review
354
- reads one bounded snapshot per market and skips unchanged persistence. Terminal
355
- groups normally return local identities without new order observations or
356
- linkage; a retained dispatch ledger keeps them eligible for fresh review and
357
- settlement.
358
-
359
- Mobile and Extension must gate attached forwarding on `attachedTpsl` plus their
360
- own rollout policy. This package change does not adopt the feature in either
361
- client. `attachedTpsl.lifecycleVerification` remains `pending`. Native
362
- activation, partial-parent-fill coverage, and automatic parent/child
363
- cancellation guarantees require venue execution evidence. The current
364
- capability only describes the implemented grouped submission, read review and
365
- explicit exact-ID cancellation.
366
-
367
- ## Durable Lighter Scale groups
368
-
369
- Lighter advertises Scale as a provider source capability for active markets.
370
- Preview, validation and placement share fixed-grid ladder normalization and
371
- reject collapsed price ticks, underfunded rungs and unsupported execution
372
- fields. Sizes conserve whole base lots; USD sizing bounds the sum of every
373
- rung's limit notional. Margin and reduce-only reservations are checked before
374
- placement and again before each send. Caller-supplied slippage, trigger,
375
- attached-protection, time-in-force, full-close and other strategy fields are
376
- rejected rather than ignored.
377
-
378
- `getScalePriceLadder` accepts optional `sizing` with either an exact base `size`
379
- or a maximum quote `usdAmount`, plus optional `skew`. Lighter returns
380
- `sizingPreview` with exact per-rung sizes, totals, size precision and the venue's
381
- maker minimums. Preview uses the placement builder without account reads,
382
- key setup or signing. It rounds base size down and never exceeds the quote
383
- budget; account collateral and reservations still require placement validation.
384
- Omitting `sizing` preserves the price-only result. Providers without sizing
385
- support leave `sizingPreview` absent, so clients must check before using it.
386
-
387
- Each group persists wallet, network, account, trading slot, immutable rung
388
- intent and signed dispatch identity before transport. Placement polls through
389
- bounded venue visibility lag and stops after unresolved acceptance;
390
- reconnection never resumes or replays it. `getScaleOrderGroups()` lists local
391
- ownership, including groups without any venue order ID.
392
- `reviewScaleOrderGroups({ providerId })` reconciles with registered read
393
- authority and may sign authentication, but does not register a trading key or
394
- send financial transactions. Aggregated review requires an explicit provider.
395
- Controller calls reject changes to the issuing account, network or provider
396
- while awaiting readiness or results.
397
-
398
- `OrderResult.submittedSize` includes attempted children whose acceptance is
399
- unknown. `acceptedSize` and `weightedAverageLimitPrice` are omitted while any
400
- attempted child remains uncertain. `acceptedChildren` retains confirmed
401
- accepted children, including canceled children; `childOrderIds` contains
402
- resting children only. Filled quantities require authoritative venue data;
403
- limit prices never stand in for execution prices. Wholly unknown groups never
404
- create synthetic `Order` rows. Real venue rows that match the persisted intent
405
- carry `strategyGroupId`. A live row that contradicts a durably rejected child
406
- remains an ordinary order without that group's attribution.
407
-
408
- Cancel with `{ orderType: 'scale', orderId: groupId, symbol }`. Only exact
409
- group children are canceled, using the currently registered trading slot even
410
- when placement belonged to a previous slot. Unknown dispatches remain protected
411
- until exact terminal transaction proof, or durable expiry proof followed by
412
- fresh absent transaction and order history, allows settlement. Explicit group
413
- review can retire expired absent children without canceling accepted siblings.
414
- Fresh exact rows can recover a pending child's receipt; recovered outcomes
415
- still require explicit acknowledgment before another financial write. Proven
416
- terminal cancellation never initializes a trading signer. Order history
417
- traversal is bounded and incomplete or inconsistent history fails closed. The
418
- local journal retains at most 64 groups and only reclaims proven-terminal
419
- groups. Local disk loss cannot reconstruct an unknown group's identity;
420
- consumers must preserve the configured durable storage.
421
-
422
- Clients must gate availability on `getOrderCapabilities` and route review and
423
- cancellation to the owning provider. An HTTP acknowledgment or group ID never
424
- proves a fill or successful cancellation.
425
-
426
- ## Lighter native TWAP preparation
427
-
428
- Lighter TWAP remains unavailable in `getOrderCapabilities`. Default placement refuses
429
- before signer setup. `getTwapOrders` rejects rather than reporting an empty
430
- inventory, and `cancelOrder` with `orderType: 'twap'` refuses before signing.
431
- A generic cancel transaction acknowledgment cannot establish that a native
432
- schedule has terminated or that no later slices will execute.
433
-
434
- The `utils/lighterTwap` preparation primitive validates exact amount and price
435
- bounds, rounds price protection inward by side, converts whole minutes to a
436
- future millisecond expiry, and rejects randomization. It does not sign, submit,
437
- persist an operation, or expose a supported strategy. It does not impose the
438
- Hyperliquid duration rules or claim that the venue accepts every prepared value.
439
- The caller must supply a millisecond clock and current authoritative market
440
- precision and reference price before any future lifecycle integration.
441
-
442
- Enabling TWAP requires authoritative cumulative parent-fill semantics, complete
443
- child-fill attribution and terminal cancellation evidence. Persisted ownership,
444
- restart reconciliation and uncertain-dispatch recovery must then be integrated
445
- and validated before enabling placement. Reducing a position to zero is not
446
- termination: Lighter documents that reduce-only schedules keep attempting slices
447
- until expiry.
448
-
449
- ## Gated Lighter native TWAP lifecycle
450
-
451
- The provider's default-off `nativeTwapTestnetProbe` constructor option enables
452
- bounded source-validation placement and cancellation on testnet. It rejects
453
- mainnet construction, requires explicit and independently observed 1x leverage,
454
- exact size within the venue's parent minimums and a maximum 20 USD initial
455
- protected notional, and refuses unsupported strategy fields. Normal controller
456
- construction does not enable this option. `getOrderCapabilities` and product
457
- `getTwapOrders` remain unavailable pending native mapping proof.
458
-
459
- Before signing a native schedule, a separate durable journal records immutable
460
- wallet, network, account, original key slot, market, exact intent and client ID.
461
- Signed nonce, hash and transaction expiry are recorded separately from schedule
462
- expiry, and dispatch attempt is persisted before transport. Lost responses and
463
- restarts retain obligations without replaying CreateOrder. An unresolved owned
464
- schedule prevents another on the same market. The journal is bounded to 64
465
- records and 16 cancellation attempts per record; it does not silently prune
466
- unresolved or historical records.
467
-
468
- `getNativeTwapObservations()` uses existing registered read authority, never key
469
- registration or financial dispatch. It reports exact parent and child rows,
470
- unaggregated child trades, matching transaction outcomes, candidate normalized
471
- fills and explicit mapping issues. Parent identity includes account, market,
472
- client ID, side, size, price, expiry and nonce. Pagination must exhaust, repeated
473
- cursors fail, snapshots must remain stable, and parent/child/trade quantities
474
- must agree. A failed read or an omitted parent is uncertainty, not an empty
475
- schedule inventory or a completed order. Unrelated orders are excluded from
476
- parent-child reconciliation.
477
-
478
- `accountOrders` has a documented retention window: last 10K active orders or
479
- last 1K inactive orders within 24 hours. History scans retain raw evidence when
480
- an exact row is absent, but canonical projection still requires a stable exact
481
- parent reread. Missing retained history therefore remains an explicit obligation.
482
- The current native mapping gate prevents terminal observations from releasing
483
- cleanup obligations. The settlement code additionally requires a matching
484
- executed cancellation for canceled parents and elapsed expiry for expired
485
- parents. Disconnecting the provider never completes or deletes schedules.
486
-
487
- Native slice minimums, cumulative parent/child semantics, terminal timestamps
488
- and cancellation race ordering still require testnet evidence.
489
- Candidate observations and unit fixtures are not venue proof. The constructor
490
- probe option is not exposed as a production feature flag or controller action.
491
-
492
- ## Lighter post-only limits
493
-
494
- Ordinary `limit` orders accept `timeInForce: 'ALO'`. Validation and placement
495
- require active market metadata, native price/size grids and maker minimums.
496
- Unsupported strategy, attached protection and caller client-ID fields are
497
- rejected before signer setup. Fresh public native book reads reject a crossing
498
- price before setup and again inside the serialized write section. A book read
499
- older than five seconds fails closed. Native TIF 2 is the final venue guard if
500
- the book changes after local validation; GTT and IOC behavior is unchanged.
501
-
502
- A successful ordinary placement receipt means the transaction was submitted;
503
- it does not assert that a post-only order rested or filled. A racing book can
504
- still produce native `canceled-post-only` history. Reconcile exact order state
505
- through ordinary venue reads. Response loss retains the exact client handle in
506
- the failure receipt and the inherited durable nonce/transaction journal blocks
507
- replay across restart until authoritative recovery. No automatic retry is added.
508
- This transport support does not advertise Chase or establish its venue proof.
509
-
510
- ## Bounded Lighter Chase lifecycle
511
-
512
- The default leaves Chase unavailable. Set
513
- `clientConfig.providerCredentials.lighter.chaseTestnetProbe: true` to enable the
514
- bounded probe on the actual testnet provider with an injected signer. Controller
515
- registration omits this setting on mainnet; direct mainnet
516
- construction rejects it.
517
- Enabled testnet capabilities include Chase. Production remains unavailable;
518
- client integration and live venue acceptance are still required for rollout.
519
-
520
- The probe uses the existing `orderType: 'chase'` contract with exact base size,
521
- explicit existing 1x leverage, a 20 USD aggregate notional ceiling, an interval
522
- of at least 1,000 ms, duration from one interval through 300,000 ms, at most 20
523
- reprices, and an adverse distance strictly between 0 and 10,000 bps. Defaults are
524
- 15,000 ms interval, 60,000 ms duration, one reprice and 100 bps distance. It starts
525
- from a flat account with no unrelated open orders or exposure. Every replacement
526
- requires account position quantity to match the exact cumulative owned fills,
527
- plus no outstanding prior child. Existing position value plus replacement
528
- notional must still fit the same ceiling. Native minimums apply to each remaining
529
- child; a remainder below minimum stops rather than enlarging the order.
530
-
531
- Probe transport currently supports opening orders only; reduce-only, USD sizing,
532
- attached protection and other strategy fields remain refused at the probe
533
- boundary. The dedicated coordinator retains reduce-only intent in its internal
534
- contract, but no product or probe support is claimed for that route. No automatic
535
- leverage change, new slot allocation policy, key replacement, fee or PnL invention
536
- is introduced.
537
-
538
- The native public order book supplies individual owner-tagged orders. Quotes
539
- remove every same-side account order, preserve opposing liquidity, and use the
540
- market's fixed price tick. Missing external liquidity, stale responses, malformed
541
- identity or a crossed book stop financial continuation. Each replacement uses
542
- newly read quotes and native post-only TIF 2.
543
-
544
- A durable journal binds wallet, network, account, original key slot, market,
545
- immutable budget and session handle. Each exact child is persisted before
546
- signing, its hash/nonce/expiry before dispatch, and attempted state before send.
547
- A serial tick cannot replace a child until exact terminal order state, exhaustive
548
- unaggregated fill history and a stable reread agree. Exact terminal child state
549
- settles cleanup even when a fill beats its cancel transaction. Cancel transaction
550
- outcomes provide attribution and retire definitively failed attempts for explicit
551
- retry. Fills observed during cancellation reduce the next size. Acknowledgments
552
- and missing rows never prove termination. An attempted placement absent after
553
- signed expiry plus clock slack can settle only with definitive transaction and
554
- exact-order evidence; acknowledged or previously visible placements remain owned.
555
- There are at most 64 retained sessions, 21 children per session and 16 cancel
556
- attempts per child; records are never silently pruned.
557
-
558
- `getChaseOrders()` returns provider-bound public state, or an empty list for an
559
- unbound or recordless wallet, including with the probe off. If current venue
560
- discovery reports no account, previously verified wallet/network journals remain
561
- visible. Suspension retains their pending cleanup locally without enabling venue
562
- reads, signing or registration. Repeated local suspension and cancellation preserve
563
- the child's cancellation capacity and existing dispatch identities, including across
564
- provider restart. Cleanup remains `termination_pending` with an explanatory native
565
- record error until the original account and key authority can reconcile it.
566
- `PerpsController:getChaseOrderOwnership({handle, providerId, owner?})` reads one
567
- exact stable handle from validated local storage. `available` includes its original
568
- wallet, provider, network, account and trading-key slot, every durable child in order,
569
- placement/cancellation phases and public transaction identities, and each child's
570
- last exact persisted venue ID, terminal flag and decimal fill quantities. Superseded
571
- children remain included. An absent observation leaves attempted or acknowledged
572
- placement unresolved. These observations are not a fresh venue reconciliation.
573
- The optional `owner` binds a repeat read to the full original identity.
574
-
575
- This read works with the probe off, without a signer and after venue authority
576
- has disappeared. It does not bind/rebuild transport, allocate keys, sign, resume,
577
- cancel or write storage. Prepared/signed attempts retain their recorded phases.
578
- Account, network, provider, key/session or controller lifetime changes across awaits
579
- reject the read. Missing handles return `unavailable` with `not_found`; a mismatched
580
- expected owner returns `owner_mismatch`. Missing storage never becomes an available
581
- empty inventory, and malformed/ambiguous records reject. Returned IDs grant no
582
- cleanup authority under another wallet, account, network or key.
583
-
584
- Pass the exact `OrderResult.orderId` as `handle`, preserve all opaque IDs and
585
- reconcile each returned child independently before explicit cleanup for that handle.
586
- Aggregated mode routes only the requested `providerId`. HyperLiquid reports
587
- `unsupported` for this durable read and retains its existing `getChaseOrders()`
588
- behavior. Full Lighter Chase readiness still requires client integration and venue
589
- proof; the default-off/testnet gates remain unchanged. TWAP remains separate:
590
- Lighter's public TWAP lifecycle read refuses support until authoritative parent fills
591
- and terminal semantics are established. Local children do not establish a complete
592
- TWAP schedule.
593
-
594
- `PerpsController:reconcileChaseOrderCancellation({handle, providerId, owner,
595
- clientOrderId, cancellation: {nonce, txHash, expiresAt}})` reconciles the latest
596
- already attempted cancellation of a stopped handle. Preserve the full original
597
- owner and exact latest child/cancellation transaction identity from durable history.
598
- Lighter observes venue evidence and persists management settlement under the existing
599
- owner lock and session fence. The service receives only observation, clock and
600
- session-check functions, so it cannot allocate a nonce, sign or send another
601
- cancellation even when an acknowledged cancellation becomes failed and the child
602
- remains open. Existing registered read authority may create an authentication client
603
- and read nonce metadata, but it never registers a key or submits a transaction.
604
-
605
- A proven terminal handle returns `settled` with its public `order`; uncertain
606
- visibility, missing acknowledgement or failed/lost venue replies return `unresolved`.
607
- A missing original cancellation, active handle, wrong original identity or malformed
608
- inventory rejects before venue observation. Providers without this operation return
609
- `unsupported`; aggregated routing never substitutes ordinary cancellation. A lost
610
- public reconciliation reply remains unresolved and grants no authority to replay
611
- `cancelOrder`. Ordinary explicit cancellation retains its existing behavior.
612
-
613
- `getNativeChaseRecords()` exposes exact local cleanup identities for diagnostics.
614
- `cancelOrder({orderType: 'chase', orderId: handle, symbol, providerId: 'lighter'})`
615
- explicitly terminates an owned handle. A wrong-symbol request leaves its active
616
- duration cleanup intact. Confirmed explicit cleanup succeeds even when the
617
- record retains an earlier failure cause and terminal status.
618
- `suspendChaseOrders()` interrupts starts waiting on setup as well as in-flight
619
- and scheduled continuation before attempting exact cleanup. This Lighter probe
620
- cancels the last child on backgrounding and duration, repricing or distance limits.
621
- Confirmed cleanup reports `canceled` with no resting order ID; the native record
622
- retains the first cause in `stopReason`. Unknown cleanup reports
623
- `termination_pending`. HyperLiquid suspension leaves its child resting. The
624
- Lighter timer uses the absolute duration deadline; network latency and suspended
625
- execution can delay venue cleanup. Account changes and
626
- provider teardown interrupt synchronously. Reconnect exposes interrupted records
627
- as `termination_pending` and never restarts the financial loop. Unknown cancel or
628
- lost-response ownership remains visible, including across process restart and
629
- original-slot changes; cleanup requires the original available authority and
630
- existing recovery-ledger conditions.
631
-
632
- Exact order lookup has the venue's limited retention window. Missing retained
633
- history or unsafe numeric IDs fail closed and may require separate manual
634
- recovery; they do not authorize a replacement. All lifecycle checks above are
635
- source behavior. Live post-only crossing, fill/cancel races and bounded reprice
636
- behavior require venue acceptance checks.
637
-
638
- `utils/lighterTwapReconciliation.reconcileLighterTwapObservation` reconciles
639
- complete native parent/child rows and unaggregated trades against persisted
640
- signed intent. `identifyLighterTwapParent` validates immutable parent ownership
641
- without requiring fill reconciliation, so incomplete history does not block
642
- exact cancellation. Neither utility proves venue termination. Numeric and
643
- string trade IDs must agree; trade provenance allows 30 seconds of clock skew.
644
-
645
- Native TWAP and Chase probes share one unresolved-account exclusion, including
646
- across provider instances and restarts. Unverified TWAP terminal observations
647
- retain that exclusion. The provider class is not a package export, controller
648
- registration omits probe constructor options, and observation collection needs
649
- a direct Lighter provider rather than the aggregated provider. Probe callers
650
- must supply a development integration; these are not enabled product features.
651
-
652
115
  ## Contributing
653
116
 
654
- This package is part of a monorepo. Instructions for contributing can be found
655
- in the [monorepo README](https://github.com/MetaMask/core#readme).
656
-
657
- ### Native resting-order edits
658
-
659
- Lighter `editOrder` modifies the same exact venue order with transaction type 17.
660
- It supports price or size changes to verified unfilled ordinary active perpetual
661
- limits with GTC or post-only time-in-force. Side, type, time-in-force, reduce-only
662
- and expiry stay fixed. Trigger, linked protection and durably recorded Scale,
663
- Chase and position-protection children are refused. Partially filled orders are
664
- also refused because the pinned signer proof does not establish total-versus-
665
- remaining amount semantics for those orders.
666
-
667
- Pass unsafe int64 venue IDs as canonical decimal strings. Core decodes raw venue
668
- and signed JSON with ordinary string parsing, preserving integer identities
669
- without Node reviver extensions or rewriting the signed transaction. It checks
670
- the refreshed market grid, minimums and native integer widths before signing,
671
- and rereads the target after signing. The pinned seven-position
672
- `_signModifyOrder` tuple has no order-version or resting-expiry argument, so a
673
- fill or cancel can still race after that final read.
674
-
675
- `OrderResult.orderEdit` reports requested price and size, a durable status and an
676
- optional exact same-order observation. `success:true` requires exact transaction
677
- execution and an unfilled open observation with the requested price, size and
678
- remaining size. HTTP acceptance, unchanged fields, missing rows, lookup failures
679
- and partial-fill races remain pending. An exactly observed filled or canceled
680
- order after proved execution is terminal with `success:false`; it is not an edit
681
- success or a fabricated fill receipt. No cancel/re-place fallback runs.
682
-
683
- Core persists unsigned intent before signing and records the exact nonce, hash,
684
- expiry and original wallet/network/account/key before dispatch. It never stores
685
- signed payloads or keys in the edit journal. After interruption or restart,
686
- calling `editOrder` on that ID reconciles the retained intent using the original
687
- registered local key before financial setup. The call returns that prior outcome
688
- without submitting another edit, including when the new desired fields differ.
689
- Pending records cannot be overwritten by retries. Exact failed or proved-unsent
690
- attempts, and unaccepted exact hashes confirmed absent after signed expiry plus
691
- clock slack and an exact target reread, permit a subsequent explicit retry.
692
- Earlier acceptance or execution proof remains pending through later lookup loss.
693
-
694
- This Core contract does not establish venue edit effects, Mobile bridge support
695
- or delivered client parity. Mobile adoption and testnet same-order price/size
696
- lifecycle proof remain separate validation work.
697
-
698
- The Chase probe accepts Mobile's explicit `usdAmount` only when its downward-grid
699
- size agrees with the captured current price and fresh venue quote. The USD amount
700
- becomes the durable aggregate budget for original and replacement children, within
701
- the 20 USD limit. Preparation is repeated after signer readiness, and existing
702
- late dispatch, 1x, opening-only, fill and child-ownership checks remain required.
117
+ This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme).