Skip to content

feat(perps): add provider-routed Scale price normalization - #10021

Merged
abretonc7s merged 5 commits into
mainfrom
feat/perps-export-scale-price-normalizer
Sep 1, 2026
Merged

feat(perps): add provider-routed Scale price normalization#10021
abretonc7s merged 5 commits into
mainfrom
feat/perps-export-scale-price-normalizer

Conversation

@abretonc7s

@abretonc7s abretonc7s commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Explanation

Adds the provider-neutral PerpsController:getScalePriceLadder API. providerId is optional: omitting it uses the active/default provider, while supplying it routes explicitly in aggregated mode.

Providers own market metadata and venue formatting. HyperLiquid precision is no longer exposed through a public venue-specific helper.

References

Validation

  • Full @metamask/perps-controller suite and coverage gate
  • 525 focused controller, aggregator, and HyperLiquid tests
  • TypeScript, ESLint, Oxfmt, changelog validation, and messenger action generation
  • Independent cross-model review approved bfe5e685c6e8c54fb46b8c446380e28bb1c6baa7

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating the Perps Controller changelog
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Low Risk
Additive read-only API with optional provider hooks; HyperLiquid scale placement only shares an internal normalization helper, so trading behavior should stay consistent while previews move off client-side venue formatting.

Overview
Adds PerpsController:getScalePriceLadder so clients can preview Scale ladder prices through the same provider routing as order placement. Optional providerId selects a venue in aggregated mode; otherwise the active/default provider is used. Results are a ready payload with venue-normalized price strings or a typed unavailable status (mirroring order-capabilities reasons).

The PerpsProvider interface gains an optional getScalePriceLadder hook, with routing implemented on AggregatedPerpsProvider and a HyperLiquid implementation that resolves market szDecimals, formats rungs, and rejects ladders whose prices collapse to duplicates. HyperLiquid getOrderCapabilities is refactored to share market lookup with the ladder path, and scale placement reuses the same normalization helper so preview and submit stay aligned.

Exports messenger action types plus GetScalePriceLadderParams / PerpsScalePriceLadder; tests cover controller, aggregator, and HyperLiquid behavior.

Reviewed by Cursor Bugbot for commit bfe5e68. Bugbot is set up for automated code reviews on this repo. Configure here.

@abretonc7s
abretonc7s marked this pull request as ready for review September 1, 2026 07:31
@abretonc7s
abretonc7s requested review from a team as code owners September 1, 2026 07:31
@abretonc7s
abretonc7s deployed to default-branch September 1, 2026 07:31 — with GitHub Actions Active
@abretonc7s abretonc7s changed the title feat(perps): export normalized Scale price ladder feat(perps): export normalized Scale price ladder [NOT-READY] Sep 1, 2026
@abretonc7s
abretonc7s marked this pull request as draft September 1, 2026 10:08
@abretonc7s
abretonc7s force-pushed the feat/perps-export-scale-price-normalizer branch from d088983 to c0a896d Compare September 1, 2026 10:48
@abretonc7s abretonc7s changed the title feat(perps): export normalized Scale price ladder [NOT-READY] feat(perps): add provider-routed Scale price normalization Sep 1, 2026
@abretonc7s
abretonc7s marked this pull request as ready for review September 1, 2026 11:02
@abretonc7s
abretonc7s deployed to default-branch September 1, 2026 11:02 — with GitHub Actions Active
@abretonc7s
abretonc7s enabled auto-merge September 1, 2026 18:21

@geositta geositta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this change against origin/main. Provider routing and Hyperliquid precision behavior are correct, and the shared normalizer keeps preview and placement formatting aligned. The two comments tighten TypeScript exhaustiveness and regression coverage without blocking this PR.

| Readonly<{
status: 'unavailable';
providerId?: PerpsProviderType;
reason: OrderCapabilitiesUnavailableReason;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we define a Scale specific unavailable reason union? OrderCapabilitiesUnavailableReason includes strategy_market_unsupported, which this API cannot return and forces consumers to handle an impossible state.

it('normalizes every rung with provider-owned market precision', async () => {
const { infoClient } = useStrategyClients();

expect(await provider.getScalePriceLadder(params)).toStrictEqual({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a parity test comparing fractional preview prices with the prices submitted by Scale placement? Preview covers fractional prices, while placement assertions use integers; exact preview and submission parity is this API’s primary contract.

@abretonc7s
abretonc7s added this pull request to the merge queue Sep 1, 2026
Merged via the queue into main with commit 93d1ecb Sep 1, 2026
51 checks passed
@abretonc7s
abretonc7s deleted the feat/perps-export-scale-price-normalizer branch September 1, 2026 22:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants