Skip to content

feat(client-utils): add activity mappers#9376

Open
n3ps wants to merge 7 commits into
mainfrom
n3ps/client-shared-mappers
Open

feat(client-utils): add activity mappers#9376
n3ps wants to merge 7 commits into
mainfrom
n3ps/client-shared-mappers

Conversation

@n3ps

@n3ps n3ps commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Explanation

Some client logic is currently duplicated across the MetaMask Extension and Mobile apps, including the activity view mappers and the number and currency formatting utilities.

The initial release of this package will include these shared functions extracted fromthe Activity list and details screens of mobile and extension:

  • mapApiTransaction - maps EVM transactions from @metamask/core-backend
  • mapKeyringTransaction - maps non-EVM transactions from @metamask/keyring-api
  • mapLocalTransaction - maps pending and local transactions from @metamask/transaction-controller

References

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
Large new mapping surface drives how users see transaction history (amounts, types, NFT payments); misclassification would be user-visible, though logic is heavily tested and mostly additive in a new package.

Overview
Replaces the @metamask/client-utils placeholder with shared activity mapping for Extension and Mobile: indexed EVM txs (mapApiTransaction), keyring txs (mapKeyringTransaction), and local/pending EVM groups (mapLocalTransaction), all emitting a unified ActivityItem model (ActivityKind, Status, tokens, fees).

The mappers encode category-specific behavior (send/receive, swaps, NFT buy/sell/mint, approvals, lending, wrap/unwrap, bridge, perps, mUSD, contract fallbacks) using helpers for CAIP asset ids, value-transfer parsing, fees, and mainnet token metadata. Runtime deps are added on core-backend, transaction-controller, keyring-api, and related packages; README dependency graph is updated.

Coverage is large fixture-driven Jest suites; tests note mapApiTransaction vs mapLocalTransaction can disagree on some stakes (e.g. Lido classified as lendingDeposit vs deposit).

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

@n3ps n3ps requested review from a team as code owners July 2, 2026 13:41
@n3ps n3ps force-pushed the n3ps/client-shared-package branch from 5e9d190 to 077b222 Compare July 2, 2026 13:44
@n3ps n3ps force-pushed the n3ps/client-shared-mappers branch from 7ab180a to f86edbc Compare July 2, 2026 13:45
@n3ps n3ps force-pushed the n3ps/client-shared-package branch 2 times, most recently from c04ad31 to 97ef77d Compare July 2, 2026 14:01
@n3ps n3ps force-pushed the n3ps/client-shared-mappers branch from f86edbc to 9e724dc Compare July 2, 2026 14:01
Comment thread packages/client-utils/src/mappers/api-transaction-mapper.ts
Comment thread packages/client-utils/src/mappers/local-transaction-mapper.ts
@n3ps n3ps force-pushed the n3ps/client-shared-package branch from 9f7963e to 7a35be8 Compare July 2, 2026 14:49
@n3ps n3ps changed the title feat: add transaction activity mappers to @metamask/client-shared feat: add transaction activity mappers to @metamask/client-utils Jul 2, 2026
@n3ps n3ps force-pushed the n3ps/client-shared-mappers branch from 9e724dc to ae0bac9 Compare July 2, 2026 14:51
Comment thread packages/client-utils/src/mappers/helpers/transactions.ts
Comment thread packages/client-utils/src/mappers/api-transaction-mapper.ts
Comment thread packages/client-utils/src/mappers/api-transaction-mapper.ts
Base automatically changed from n3ps/client-shared-package to main July 2, 2026 15:33
@n3ps n3ps force-pushed the n3ps/client-shared-mappers branch from ae0bac9 to 1a09b92 Compare July 2, 2026 15:58
Comment thread packages/client-utils/src/mappers/local-transaction-mapper.ts
@n3ps n3ps force-pushed the n3ps/client-shared-mappers branch from e4d60a2 to 67c8a92 Compare July 2, 2026 17:08

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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.

Reviewed by Cursor Bugbot for commit 24489af. Configure here.

Comment thread packages/client-utils/src/mappers/local-transaction-mapper.ts
@n3ps n3ps force-pushed the n3ps/client-shared-mappers branch 3 times, most recently from 1d4aed0 to f91c847 Compare July 2, 2026 17:32
n3ps and others added 7 commits July 2, 2026 13:33
Add the transaction activity mappers and shared activity types on top of
the `@metamask/client-utils` package scaffold:

- `mapApiTransaction` for mapping EVM API transactions to activity items
- `mapKeyringTransaction` for mapping keyring transactions to activity items
- `mapLocalTransaction` for mapping local transaction groups to activity items
- Shared activity types (`ActivityItem`, `ActivityKind`, `Status`, etc.)

Also adds the runtime dependencies these mappers require and comprehensive
unit tests with fixtures.

Co-authored-by: Cursor <cursoragent@cursor.com>
Permit2 `approve(token, spender, amount, expiration)` transactions are
classified as `tokenMethodApprove`, but `txParams.to` is the Permit2
contract rather than the approved ERC-20. The mapper previously used
`to` as the spending-cap token, so Permit2 approvals showed the wrong
`assetId`/symbol.

Detect the Permit2 approve selector and decode the approved token from
the first calldata argument instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
On the buy path, getNftPaymentTransfer treated any outbound native
(`normal`) transfer as the NFT payment, so an inbound NFT plus an
unrelated native send in the same indexed transaction could be mapped as
`nftBuy` instead of `receive`.

Only count a sent transfer as payment when it goes to the NFT
counterparty (direct sale) or to the contract being called
(marketplace/router via `transaction.to`).

Co-authored-by: Cursor <cursoragent@cursor.com>
Rather than decoding the approved token from Permit2 calldata, the local
mapper now just classifies the activity as an approve and omits the token
when `to` is the Permit2 contract. This keeps the local mapper thin — its
job is to identify the ActivityKind — and defers accurate token data to
the API mapper, which has richer information.

Co-authored-by: Cursor <cursoragent@cursor.com>
The default contractInteraction path only attached `token` when
`token.amount` was truthy, dropping symbol/direction/assetId when the
value transfer had no amount. Attach the token whenever it is defined,
since getTokenAmountFromTransfer only returns a token with meaningful
metadata.

Co-authored-by: Cursor <cursoragent@cursor.com>
The local mapper only needs to classify an incoming NFT with native value
as an nftBuy. Drop the placeholder `token: { direction: 'in' }` (no
symbol/assetId/amount) and let the API mapper provide token and payment
details.

Co-authored-by: Cursor <cursoragent@cursor.com>
mapApiTransaction classified a `wrap` on the WETH deposit selector plus
any inbound transfer, without confirming transaction.to is the chain's
wrapped-native contract (the local mapper already requires this via
swapsWrappedTokensAddresses). Gate the wrap classification on
transaction.to matching the chain's wrapped-native address.

Co-authored-by: Cursor <cursoragent@cursor.com>
@n3ps n3ps force-pushed the n3ps/client-shared-mappers branch from f91c847 to f273ba4 Compare July 2, 2026 17:33
@n3ps n3ps changed the title feat: add transaction activity mappers to @metamask/client-utils feat(client-utils): add activity mappers Jul 2, 2026
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