Skip to content

feat(ramps-controller): diff autoramp transaction statuses - #11017

Merged
georgeweiler merged 8 commits into
mainfrom
cursor/vba-transaction-diff-b4a1
Oct 27, 2026
Merged

georgeweiler merged 8 commits into
mainfrom
cursor/vba-transaction-diff-b4a1

Conversation

@georgeweiler

@georgeweiler georgeweiler commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Explanation

The app needs to know when a virtual bank account transaction is new or has changed status, without storing amounts or bank details and without reporting the same change twice.

RampsController persists autorampTransactionRecords: for each autoramp, the epoch ms of the first successful fetch and the last seen status string per transaction id. diffAutorampTransactions is pure. The first successful fetch (including an empty one) seeds the record and calls nothing. Later fetches report a new id or a different status string, including a status that moved backwards or skipped intermediate values. A transaction missing from the page stays in the record.

refreshAutorampTransactions loads the newest page (sort_order=desc, page_size 50, no pagination), writes the next record, then calls the optional trackAutorampTransactionStatusChanged constructor callback once per change. previousStatus is omitted for a new id. A failed fetch writes nothing. Concurrent calls for the same autoramp share one request. Removing an autoramp, replacing the autoramp cursor, or discarding a foreign VBA session clears the matching records. A fetch still in flight when that autoramp leaves the cursor does not write the record or call the callback.

This is an analytics signal, so it is a callback rather than a RampsController messenger event. orderStatusChanged and autorampStatusChanged stay messenger events because the client uses them for more than tracking.

NeoBankService.listAutorampTransactions accepts an optional pageSize. Omitting it keeps the previous query.

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

BREAKING: RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS now includes NeoBankService:listAutorampTransactions. Hosts that spread that list pick it up on the package bump. Hosts that copy the action list by hand must delegate it.


Note

Medium Risk
Introduces a breaking messenger delegation requirement and new persisted VBA transaction state with analytics callbacks; behavior is guarded but hosts must wire the NeoBank action and handle migration of persisted state.

Overview
Adds persisted autoramp transaction status tracking so hosts can learn when a VBA deposit transaction is new or its MoonPay status string changed, without storing amounts or firing duplicate analytics.

RampsController gains persisted autorampTransactionRecords (per autoramp: syncedAt plus last-seen status per transaction id), the pure helper diffAutorampTransactions, and refreshAutorampTransactions, which loads the newest transaction page (page_size 50), updates the record, then invokes optional constructor callback trackAutorampTransactionStatusChanged once per new id or status change (previousStatus omitted for new ids). The first successful fetch only seeds the record; failed fetches leave it unchanged; concurrent refreshes per autoramp dedupe to one request; records are cleared when an autoramp is removed, the cursor is replaced, or a foreign VBA session is discarded, with in-flight fetches not re-writing removed autoramps.

NeoBankService.listAutorampTransactions accepts optional pageSize (page_size query). Breaking: RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS now requires NeoBankService:listAutorampTransactions delegation. New messenger action RampsController:refreshAutorampTransactions and related types are exported from the package.

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

cursoragent and others added 2 commits October 22, 2026 19:48
Persist the last seen status per autoramp transaction and publish a change only after that record is written. The first successful fetch seeds the record.

Co-authored-by: george.weiler <george.weiler@consensys.net>
Co-authored-by: george.weiler <george.weiler@consensys.net>
@georgeweiler
georgeweiler marked this pull request as ready for review October 22, 2026 20:02
@georgeweiler
georgeweiler requested review from a team as code owners October 22, 2026 20:02

@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 using default effort 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 68becb2. Configure here.

* status pass 50.
* @returns Transaction summaries from the newest page.
*/
async listAutorampTransactions(

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.

Proxy has /autoramp-transactions/ids for targeted refresh. Do we have any plan to use it (e.g. after push) vs forever listing?

@matteyusys
matteyusys self-requested a review October 26, 2026 20:00
matteyusys
matteyusys previously approved these changes Oct 26, 2026
…moval

A fetch that returns after removeAutoramp, a cursor replace, or a foreign session discard no longer writes the cleared record or publishes a status change.

Co-authored-by: george.weiler <george.weiler@consensys.net>
georgeweiler and others added 4 commits October 26, 2026 20:09
…gh a callback

The status change is only consumed as analytics, so refresh reports it through an injected tracker after the record is written instead of a messenger event.

Co-authored-by: Cursor <cursoragent@cursor.com>
…n-diff-b4a1

Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	packages/ramps-controller/CHANGELOG.md
Co-authored-by: Cursor <cursoragent@cursor.com>
`refreshAutorampTransactions` wrote the record and then called
`trackAutorampTransactionStatusChanged` for each change with no guard, so a
throwing host tracker both rejected the refresh and skipped every later
change in the batch. The record already says those statuses were seen, so
they would never be reported again.

The callback is now wrapped per change, matching the `trackKycAnalytics`
callbacks on `KycController` (#11041).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@georgeweiler
georgeweiler added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit f572afb Oct 27, 2026
49 checks passed
@georgeweiler
georgeweiler deleted the cursor/vba-transaction-diff-b4a1 branch October 27, 2026 17:00
gaohan1994 pushed a commit to gaohan1994/core that referenced this pull request Oct 28, 2026
## Explanation

Scoped release so clients can pick up MetaMask#11017 and MetaMask#11041.

- **`@metamask/ramps-controller` 27.2.0 → 28.0.0** (major). Persists
autoramp transaction statuses and reports a new id or a changed status
string through the optional `trackAutorampTransactionStatusChanged`
callback. **BREAKING:** `RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS` now
includes `NeoBankService:listAutorampTransactions`. Hosts that spread
that list pick it up on the bump. Hosts that copy the action list by
hand must delegate it. This version also includes the unpublished
`@metamask/utils` range bump to `^12.0.1` from MetaMask#11107.
- **`@metamask/kyc-controller` 0.12.1 → 0.13.0** (minor). Adds the
optional `trackKycAnalytics` constructor callbacks
(`verificationOutcome` and `statusChanged`) from MetaMask#11041. Nothing is
added to `KycControllerEvents`. This version also includes the
unpublished `@metamask/utils` range bump to `^12.0.1` from MetaMask#11107.
- **`@metamask/transaction-pay-controller` 30.3.0 → 30.3.1** (patch).
Published because `ramps-controller` is a major and this is its only
workspace dependent. The range moves from `^27.2.0` to `^28.0.0`.

Other packages with unreleased changes are deferred.

## References

- Ships MetaMask#11017
- Ships MetaMask#11041
- Also publishes the unpublished utils range bump already on main:
MetaMask#11107

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them


Made with [Cursor](https://cursor.com)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> The ramps-controller major adds a required messenger action for
autoramp transaction polling; hosts that hand-maintain delegated actions
must update or delegation fails at runtime.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2be3977. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
darkwing pushed a commit to darkwing/metamask-mobile that referenced this pull request Oct 29, 2026
## Explanation

When the VBA details screen loads an approved autoramp, it calls
`RampsController.refreshAutorampTransactions`. The controller calls
`trackAutorampTransactionStatusChanged` for a new transaction or a
status change. Mobile passes that callback from `rampsControllerInit`
and tracks **Money VBA Transaction Updated**.

This matches the schema merged in Consensys/segment-schema#785 and the
callback on MetaMask/core#11017:

- `status` is `pending` for `FundsReviewInProgress`,
`ConversionInProgress`, and `PayoutInProgress`; `completed` for
`Completed`; `failed` for `Failed`, `RejectedAml`, `RejectedFraud`, and
`RejectedMinAmount`. A vendor status outside that enum is not tracked,
because `status` and `transaction_status` are required closed enums.
- The raw vendor value stays on `transaction_status`. `previous_status`
is omitted for a new id and when the previous value is outside the enum.
- `failure_reason` is not sent. The schema's known quirk is that a
failed transaction is `status: failed` plus the raw
`transaction_status`. `failure_reason` is the onboarding failure enum.
- `kyc_status` and `provider_flow_status` are always sent. Missing state
uses `none` and `not_started`.
- `entry_point` (`add_funds_bank_account`), `vendor` (`moonpay`),
`autoramp_status` (`ready`), `currency_destination_symbol` (`mUSD`), and
`token_chain_id` (`eip155:143`) are constants. `screen_name` is omitted
because this fires from the fetch, not from a screen.
- `region` is the lowercase alpha-2 country and is omitted while
geolocation is unknown. The schema marks it required and has no unknown
value, so an invented country is not sent.
- `currency_source` is sent when the autoramp deposit rail has one.
Amounts are numbers and are omitted when not numeric.
`seconds_since_created` is computed when the callback runs and is never
negative.

`orderStatusChanged` stays a messenger subscription. It is still used
for notifications and order analytics. There is no transaction-status
messenger event.

Production fetches transactions once per autoramp while the details
screen is open. Debug builds keep refreshing on the existing details
poll so the debug sheet can show the latest status. A failed transaction
refresh does not hide deposit details. There is no new background
poller.

## Package bump

Depends on MetaMask/core#11017. This compiles
against the published `@metamask/ramps-controller` by declaring
`AutorampTransactionStatusChangedPayload` locally and attaching
`trackAutorampTransactionStatusChanged` through a constructor-options
intersection. After `@metamask/ramps-controller` includes
`refreshAutorampTransactions` and
`AutorampTransactionStatusChangedPayload`:

- Bump `@metamask/ramps-controller`.
- Import `AutorampTransactionStatusChangedPayload` from the package and
delete the local copy in `vbaTransactionAnalytics.ts`.
- Drop the intersection on the constructor options.

Until that bump, `refreshAutorampTransactions` is optional on the
controller, so an older package skips the refresh instead of crashing.
The new `NeoBankService:listAutorampTransactions` action is already
covered by spreading `RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS` once
that list includes it.

## Checklist

- [x] Unit tests for the property mapping and the details-screen refresh
- [ ] Bump `@metamask/ramps-controller` once
MetaMask/core#11017 is published

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches money/VBA deposit flows and analytics emission on transaction
refresh; behavior is guarded when the ramps package lacks
`refreshAutorampTransactions`, but incorrect mapping could skew funnel
metrics.
> 
> **Overview**
> Adds **Money VBA Transaction Updated** analytics when autoramp deposit
transaction statuses change, aligned with the Segment VBA schema.
> 
> `rampsControllerInit` passes `trackAutorampTransactionStatusChanged`
into `RampsController`, which maps vendor statuses to `pending` /
`completed` / `failed`, enriches events from Redux (KYC, region, fiat
source), and skips unknown statuses. A shared `toAnalyticsRegion` helper
normalizes geolocation for `region`.
> 
> **VBA details** now triggers
`RampsController.refreshAutorampTransactions` (once per autoramp in
production, on the existing poll in debug) instead of calling
`NeoBankService.listAutorampTransactions`. Deposit instruction loading
stays separate so a failed transaction refresh does not hide PIX
details; debug UI still shows the latest deposit status from the refresh
result.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
15246f7. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
darkwing pushed a commit to darkwing/metamask-mobile that referenced this pull request Oct 29, 2026
…ask#38322)

## **Description**

Adopts the two controller releases that the VBA / KYC analytics work
depends on, and nothing else. No app behaviour changes.

- `@metamask/kyc-controller` `^0.12.0` → `^0.13.0`
- `@metamask/ramps-controller` `^27.1.0` → `^28.0.0`

This is deliberately split out from the three analytics PRs that consume
these APIs
([MetaMask#38078](MetaMask#38078),
[MetaMask#38160](MetaMask#38160),
[MetaMask#38161](MetaMask#38161)) for
four reasons:

1. **`ramps-controller` is a major bump** (27.1.0 → 28.0.0, also
skipping 27.2.0). That is a Ramps/platform review, not an analytics
review, and it should not be buried in a PR about Segment events.
2. **One lockfile change instead of three.** If each analytics PR
bumped, whichever merged first would force the other two to re-resolve
`yarn.lock`.
3. **It makes the analytics PRs verifiable.** All three currently
reference APIs that did not exist in the installed versions, so none of
them can produce a meaningful `lint:tsc` result until this lands.
4. **Revert safety.** If the bump regresses something unrelated, it
reverts on its own.

### The breaking change is a no-op for us

`ramps-controller@28.0.0` has one breaking change:

> **BREAKING:** `RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS` now includes
`NeoBankService:listAutorampTransactions`. Hosts must delegate that
action to `RampsController`.

No code change is needed here.
[`ramps-controller-messenger.ts`](https://github.com/MetaMask/metamask-mobile/blob/main/app/core/Engine/messengers/ramps-controller-messenger/ramps-controller-messenger.ts#L47)
already spreads the package-owned list rather than enumerating actions:

```ts
actions: [
  // Spread the package-owned required list so new service actions
  // (e.g. getDefaultRedirectCallbackUrl / NeoBankService) cannot be
  // forgotten at upgrade.
  ...RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS,
  ...
],
```

and `NeoBankService` is registered as a messenger client in `Engine.ts`,
so the new action is delegated automatically.

### Reviewer note: `ramps-controller` is now duplicated in the tree

`@metamask/transaction-pay-controller@30.2.0` depends on
`@metamask/ramps-controller@^27.1.0`, so this bump un-dedupes it:

```
├─ @metamask/transaction-pay-controller@npm:30.2.0
│  └─ @metamask/ramps-controller@npm:27.1.0 (via npm:^27.1.0)
└─ metamask@workspace:.
   └─ @metamask/ramps-controller@npm:28.0.0 (via npm:^28.0.0)
```

TPC references ramps in its messenger types
(`RampsControllerGetOrderAction`,
`RampsControllerGetQuoteWithFeesAction`). Those action shapes are
unchanged in 28.0.0 — the only breaking change was the constant above —
and `lint:tsc` passes, so this is a bundle-size cost rather than a
correctness one. Flagging it so it is a conscious decision: the clean
fix is a TPC release that widens its range to `^28.0.0`, which can
follow separately.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: MetaMask/core#11017
Refs: MetaMask/core#11041
Refs: MetaMask/core#11141

## **Manual testing steps**

```gherkin
Feature: VBA and KYC flows still work on the bumped controllers

  Scenario: Autoramp transactions still load on the VBA details screen
    Given a Money account with an approved autoramp
    When the user opens the virtual bank account details screen
    Then the deposit instructions render
    And no "action not registered" error is raised for NeoBankService:listAutorampTransactions

  Scenario: KYC identity verification still launches
    Given a user part way through VBA onboarding
    When the user reaches the identity verification step
    Then the SumSub webview opens as before
    And the stored KYC status still updates when the decision arrives
```

## **Screenshots/Recordings**

N/A — dependency bump with no UI change.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable — no new code, so no new tests.
The existing ramps, KYC and ramps-messenger suites were run against the
bumped packages (12 suites, 138 tests).
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable — N/A, no new code.
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics

Not applicable: no runtime code changes. The one performance-relevant
consequence is the duplicated `ramps-controller` noted above, which is a
bundle-size effect rather than a runtime one.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Major ramps-controller bump touches VBA/autoramp and KYC-adjacent
flows; runtime wiring appears pre-covered, but regressions in money
onboarding are still possible.
> 
> **Overview**
> Dependency-only PR that upgrades **`@metamask/kyc-controller`**
(`^0.12.0` → `^0.13.0`) and **`@metamask/ramps-controller`** (`^27.1.0`
→ `^28.0.0`), with matching **`yarn.lock`** resolution. No application
logic changes beyond keeping tests aligned with the new controller
default state.
> 
> The test background snapshot adds **`autorampTransactionRecords: {}`**
under **`RampsController`**, matching new state shipped in
ramps-controller 28. **`ramps-controller-messenger.ts`** already spreads
**`RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS`**, so the 28.0 breaking
requirement to delegate **`NeoBankService:listAutorampTransactions`**
does not need a separate host change here.
> 
> This bump is split ahead of VBA/KYC analytics PRs that depend on these
package APIs. Note that **`transaction-pay-controller`** may still pull
**`ramps-controller@27.x`**, so the tree can temporarily carry two
versions until TPC widens its range.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
49c0f97. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.

4 participants