Skip to content

feat: add sortAccountIdsByLastSelected to getSessionScopes, wallet_getSession, and wallet_createSession#8255

Open
jiexi wants to merge 4 commits intomainfrom
jl/sortAccountIdsByLastSelected
Open

feat: add sortAccountIdsByLastSelected to getSessionScopes, wallet_getSession, and wallet_createSession#8255
jiexi wants to merge 4 commits intomainfrom
jl/sortAccountIdsByLastSelected

Conversation

@jiexi
Copy link
Member

@jiexi jiexi commented Mar 19, 2026

Explanation

@metamask/chain-agnostic-permission

  • Added optional sortAccountIdsByLastSelected parameter to getSessionScopes function
    • Type: (accounts: CaipAccountId[]) => CaipAccountId[]
    • When provided, sorts the accounts array within each scope (both required and optional scopes)
    • When not provided, preserves original account order

@metamask/multichain-api-middleware

  • Added required sortAccountIdsByLastSelected hook to wallet_getSession handler
    • Passes the hook to getSessionScopes when building session response
  • Added required sortAccountIdsByLastSelected hook to wallet_createSession handler
    • Passes the hook to getSessionScopes when building session scopes for approval

References

See: MetaMask/metamask-extension#41068

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 changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Medium risk because it changes the wallet_getSession/wallet_createSession handler hook contract (new required hook) and can alter returned account ordering, which may impact downstream clients relying on current ordering.

Overview
Adds an optional sortAccountIdsByLastSelected hook to getSessionScopes in @metamask/chain-agnostic-permission, allowing callers to reorder accounts within each scope (applied to both required and optional scopes, otherwise preserving existing order).

Updates @metamask/multichain-api-middleware to require and pass this hook through wallet_getSession and wallet_createSession when building sessionScopes, with accompanying test updates and changelog entries.

Written by Cursor Bugbot for commit 7fd6922. This will update automatically on new commits. Configure here.

@jiexi jiexi requested review from a team as code owners March 19, 2026 20:36
@jiexi
Copy link
Member Author

jiexi commented Mar 19, 2026

@metamaskbot preview-build

@jiexi
Copy link
Member Author

jiexi commented Mar 19, 2026

@metamaskbot publish-preview

@github-actions
Copy link
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@5.0.1-preview-f3055a72b
@metamask-previews/accounts-controller@37.0.0-preview-f3055a72b
@metamask-previews/address-book-controller@7.1.0-preview-f3055a72b
@metamask-previews/ai-controllers@0.4.0-preview-f3055a72b
@metamask-previews/analytics-controller@1.0.0-preview-f3055a72b
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-f3055a72b
@metamask-previews/announcement-controller@8.0.0-preview-f3055a72b
@metamask-previews/app-metadata-controller@2.0.0-preview-f3055a72b
@metamask-previews/approval-controller@9.0.0-preview-f3055a72b
@metamask-previews/assets-controller@3.0.0-preview-f3055a72b
@metamask-previews/assets-controllers@101.0.1-preview-f3055a72b
@metamask-previews/base-controller@9.0.0-preview-f3055a72b
@metamask-previews/base-data-service@0.0.0-preview-f3055a72b
@metamask-previews/bridge-controller@69.1.1-preview-f3055a72b
@metamask-previews/bridge-status-controller@69.0.0-preview-f3055a72b
@metamask-previews/build-utils@3.0.4-preview-f3055a72b
@metamask-previews/chain-agnostic-permission@1.4.0-preview-f3055a72b
@metamask-previews/claims-controller@0.4.3-preview-f3055a72b
@metamask-previews/client-controller@1.0.0-preview-f3055a72b
@metamask-previews/compliance-controller@1.0.1-preview-f3055a72b
@metamask-previews/composable-controller@12.0.0-preview-f3055a72b
@metamask-previews/config-registry-controller@0.1.1-preview-f3055a72b
@metamask-previews/connectivity-controller@0.1.0-preview-f3055a72b
@metamask-previews/controller-utils@11.19.0-preview-f3055a72b
@metamask-previews/core-backend@6.2.0-preview-f3055a72b
@metamask-previews/delegation-controller@2.0.2-preview-f3055a72b
@metamask-previews/earn-controller@11.1.2-preview-f3055a72b
@metamask-previews/eip-5792-middleware@3.0.1-preview-f3055a72b
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.0-preview-f3055a72b
@metamask-previews/eip1193-permission-middleware@1.0.3-preview-f3055a72b
@metamask-previews/ens-controller@19.1.0-preview-f3055a72b
@metamask-previews/error-reporting-service@3.0.1-preview-f3055a72b
@metamask-previews/eth-block-tracker@15.0.1-preview-f3055a72b
@metamask-previews/eth-json-rpc-middleware@23.1.0-preview-f3055a72b
@metamask-previews/eth-json-rpc-provider@6.0.0-preview-f3055a72b
@metamask-previews/foundryup@1.0.1-preview-f3055a72b
@metamask-previews/gas-fee-controller@26.1.0-preview-f3055a72b
@metamask-previews/gator-permissions-controller@2.1.1-preview-f3055a72b
@metamask-previews/geolocation-controller@0.1.1-preview-f3055a72b
@metamask-previews/json-rpc-engine@10.2.3-preview-f3055a72b
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-f3055a72b
@metamask-previews/keyring-controller@25.1.0-preview-f3055a72b
@metamask-previews/logging-controller@8.0.0-preview-f3055a72b
@metamask-previews/message-manager@14.1.0-preview-f3055a72b
@metamask-previews/messenger@0.3.0-preview-f3055a72b
@metamask-previews/multichain-account-service@7.1.0-preview-f3055a72b
@metamask-previews/multichain-api-middleware@1.2.7-preview-f3055a72b
@metamask-previews/multichain-network-controller@3.0.5-preview-f3055a72b
@metamask-previews/multichain-transactions-controller@7.0.2-preview-f3055a72b
@metamask-previews/name-controller@9.1.0-preview-f3055a72b
@metamask-previews/network-controller@30.0.0-preview-f3055a72b
@metamask-previews/network-enablement-controller@5.0.0-preview-f3055a72b
@metamask-previews/notification-services-controller@23.0.0-preview-f3055a72b
@metamask-previews/permission-controller@12.2.1-preview-f3055a72b
@metamask-previews/permission-log-controller@5.0.0-preview-f3055a72b
@metamask-previews/perps-controller@1.3.0-preview-f3055a72b
@metamask-previews/phishing-controller@17.0.0-preview-f3055a72b
@metamask-previews/polling-controller@16.0.3-preview-f3055a72b
@metamask-previews/preferences-controller@23.0.0-preview-f3055a72b
@metamask-previews/profile-metrics-controller@3.1.1-preview-f3055a72b
@metamask-previews/profile-sync-controller@28.0.0-preview-f3055a72b
@metamask-previews/ramps-controller@12.0.0-preview-f3055a72b
@metamask-previews/rate-limit-controller@7.0.0-preview-f3055a72b
@metamask-previews/react-data-query@0.0.0-preview-f3055a72b
@metamask-previews/remote-feature-flag-controller@4.1.0-preview-f3055a72b
@metamask-previews/sample-controllers@4.0.3-preview-f3055a72b
@metamask-previews/seedless-onboarding-controller@9.0.0-preview-f3055a72b
@metamask-previews/selected-network-controller@26.0.3-preview-f3055a72b
@metamask-previews/shield-controller@5.0.2-preview-f3055a72b
@metamask-previews/signature-controller@39.1.0-preview-f3055a72b
@metamask-previews/storage-service@1.0.0-preview-f3055a72b
@metamask-previews/subscription-controller@6.0.2-preview-f3055a72b
@metamask-previews/transaction-controller@63.0.0-preview-f3055a72b
@metamask-previews/transaction-pay-controller@17.1.0-preview-f3055a72b
@metamask-previews/user-operation-controller@41.1.0-preview-f3055a72b

notifications = [];
}

const sortedAccounts = sortAccountIdsByLastSelected
Copy link
Member

Choose a reason for hiding this comment

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

[nit] this name can be misleading, since we are not always sorting these accounts, sortedAccounts could actually be unsorted if sortAccountIdsByLastSelected is not provided.

we could name the function param caipAccountIds, and this variable accounts for example (open to other suggestions)

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.


const sortedAccounts = sortAccountIdsByLastSelected
? sortAccountIdsByLastSelected(accounts)
: accounts;
Copy link

Choose a reason for hiding this comment

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

Sorting before merge loses order for overlapping scopes

Low Severity

sortAccountIdsByLastSelected is applied inside getNormalizedScopesObject (per-scope, before merge), but getSessionScopes then calls mergeNormalizedScopes which concatenates and deduplicates accounts from required and optional scopes via getUniqueArrayItems. When the same scope string appears in both requiredScopes and optionalScopes with different accounts, the merge disrupts the sorted order — the final array reflects required-first insertion order, not the result of sorting all accounts together.

Additional Locations (1)
Fix in Cursor Fix in Web

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.

3 participants