feat(perps-controller): add scaleSkew to Scale orders - #9919
Draft
abretonc7s wants to merge 2 commits into
Draft
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation
TAT-3723 added the
scaleorder type to@metamask/perps-controllerasscaleMinPrice/scaleMaxPrice/scaleNumOrders, with the size spread evenly across the ladder. The product spec calls for weighting that ladder toward one end of the range, and there was no parameter for it — which blocks TAT-3812, where Size Skew is a user-facing input on the mobile order form.This adds
OrderParams.scaleSkew?: number.Behaviour. Rung weights ramp linearly from 1 at index 0 to
scaleSkewat the last index, in ladder order — ascending price,scaleMinPricetoscaleMaxPrice, for a buy and a sell alike. It does not flip for a short. Above 1 puts more size atscaleMaxPrice, below 1 atscaleMinPrice. Omitted or exactly1takes the existing even-split path with no behaviour change.Allocation, and why the two paths differ. Sizes are allocated in whole units of the asset's size grid, never in floating notional that is re-floored later, so the rungs sum to exactly the size that was validated. The skewed path floors each rung to
floor(weight / sumOfWeights × totalUnits)and gives the leftover units to the rungs with the largest discarded fraction, ties by ascending index. The even path keeps putting its whole leftover on the first rung — 11 units across 3 rungs is still5, 3, 3. That asymmetry is deliberate: dumping the leftover on rung 0 under a skew above 1 would push size back toward the end of the ladder the caller weighted away from.Validation.
scaleSkewis registered as ascale-owned strategy field, so carrying it on any other order type is rejected with the existingORDER_STRATEGY_PARAMS_NOT_SUPPORTEDrather than silently ignored. A supplied value that is not a finite number above 0 is rejected byvalidateOrderParamswith a newORDER_SCALE_SKEW_INVALID, with no network call and nothing signed. The value is used exactly as given — clients coerce their input to two decimals, and re-rounding here would place a ladder weighted differently from the one the form previewed.Per-rung minimums needed no new check.
#buildScaleLadderalready applies the venue's per-order minimum to the real grid sizes before anything is signed, andvalidateStrategyNotionaldeliberately skipsscalefor that reason. A skew that pushes a rung under the minimum, or onto a zero size-grid slice, is refused there with the existingORDER_SCALE_NOTIONAL_TOO_SMALL/ORDER_SCALE_SIZE_TOO_SMALL— the batch order action is never sent.Notable API effects.
splitScaleSizesgains an optionalskewparameter and stays the single source of truth for the ladder's sizes; extending it rather than adding a sibling export means a client previewing a ladder and the placement path cannot disagree at the rounding. The remainder rule for both paths is documented on its JSDoc. The signature change is source-compatible for existing callers, andORDER_SCALE_SKEW_INVALIDis additive to thePerpsErrorCodeunion. Suborders remain GTC, rung count staysSCALE_ORDER_COUNT(2..20), and total ladder margin is still checked at placement.Validation run. Three targeted suites (212 tests) covering the ramp in both directions, the tie-break, grid-unit sum invariants, very high skew, the starved-rung boundary, invalid values, and skew-1 equivalence with the untouched even path; a provider test asserting the exact skewed sizes reach
exchangeClient.order, and thatorderis never called on a refusal. Changed-file ESLint, Prettier and jest all pass, the changelog validates, and the root build emitsskew?: numberinto the published type declarations. Existing even-distribution scale placement and the other order types are unchanged.References
splitScaleSizesrather than reimplementing the ramp. Note thatpackage.jsonexposes./utils/*and not a bare./utils, so the import is either@metamask/perps-controller(root) or@metamask/perps-controller/utils/index.Checklist
scaleSkewis optional, thesplitScaleSizessignature change is source-compatible for existing callers, and the new error code is additive