Skip to content

Commit 044726b

Browse files
meltingice1337metamaskbotamitabh94
authored
feat: delegate AuthenticationController:getBearerToken in RampsServic… (MetaMask#30319)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** This PR adopts the breaking messenger contract introduced in `@metamask/ramps-controller` for [TRAM-3502](https://consensyssoftware.atlassian.net/browse/TRAM-3502), which moves the Buy widget API call from unauthenticated to authenticated using a bearer token sourced from `AuthenticationController`. **Why:** The Buy widget endpoint on the ramps API has been gated behind authentication. Without sending an `Authorization: Bearer <token>` header on `getBuyWidgetUrl`, mobile users will be unable to launch the Transak buy flow. **What changed in core (the dependency):** - `RampsService.getBuyWidgetUrl` now fetches a bearer token via `AuthenticationController:getBearerToken` and sends it as an `Authorization` header. - `RampsServiceMessenger`'s `AllowedActions` was widened from `never` to include `AuthenticationController:getBearerToken` — i.e. consumers (this app) **must** delegate that action into the ramps messenger or the call will throw. - See the core PR for the full contract change: `<link-to-core-PR>`. **What this PR does in mobile:** 1. Bumps `@metamask/ramps-controller` to the new major version (currently consuming the preview build `@metamask-previews/ramps-controller@<preview-version>` while the core PR is in review; will switch to `^14.0.0` once published). 2. Delegates `AuthenticationController:getBearerToken` into the `RampsServiceMessenger` at the point where the messenger is constructed in the engine/controller-init layer. 3. Surfaces the new failure modes (wallet locked / user signed out / token fetch failure) to the Buy entry points so the user gets a usable error rather than an unhandled rejection. ## **Changelog** CHANGELOG entry: null <!-- This PR has no end-user-visible UI change on the happy path. The Buy flow behaves identically when the user is signed in; the only user-visible difference is improved error handling on signed-out / locked states, which is captured in the relevant feature changelog by the entry-point change, not here. If release engineering prefers an entry, suggested wording: "Improved Buy widget reliability by authenticating requests to the ramps API." --> ## **Related issues** Fixes: [TRAM-3502](https://consensyssoftware.atlassian.net/browse/TRAM-3502) Depends on (core): `<link-to-core-PR>` — must be merged and released to NPM before this PR can leave draft. ## **Manual testing steps** ```gherkin Feature: Buy widget authentication Scenario: Signed-in user opens the Buy widget Given the user is signed in and the wallet is unlocked And the user has selected a token that supports Transak When the user taps "Buy" and proceeds to the Transak provider Then the Buy widget URL loads successfully And the upstream request to the ramps API includes an "Authorization: Bearer <token>" header And Transak opens in the in-app browser as before Scenario: Wallet-locked user attempts to open the Buy widget Given the wallet is locked When the user taps "Buy" and proceeds to the Transak provider Then the user sees a clear error state (not a silent failure or crash) And no unauthenticated request is sent to the ramps API Scenario: Signed-out user attempts to open the Buy widget Given the user is signed out of profile sync / authentication When the user taps "Buy" and proceeds to the Transak provider Then the user sees a clear error state And no unauthenticated request is sent to the ramps API Scenario: Bearer token call fails transiently Given the AuthenticationController fails to mint a bearer token When the user taps "Buy" and proceeds to the Transak provider Then the failure is surfaced as a user-facing error And retrying after the underlying auth issue is resolved succeeds ``` **How to verify the Authorization header on-device:** - Point a debugging proxy (Charles / mitmproxy) at the device. - Trigger the Buy flow and inspect the request to `https://on-ramp.api.cx.metamask.io/providers/<provider>/buy-widget`. - Confirm an `Authorization: Bearer <jwt>` header is present. ## **Screenshots/Recordings** ### **Before** <!-- Recording of Buy widget on current `main`: request to /buy-widget has no Authorization header. --> ### **After** https://github.com/user-attachments/assets/b45d9a6e-3534-46f1-b51f-1d42637c32d0 <!-- Recording of Buy widget on this branch: same UX, request now includes Authorization: Bearer <token>. Plus recordings of the locked-wallet and signed-out error states. --> ## **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 - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] 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) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **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. [TRAM-3502]: https://consensyssoftware.atlassian.net/browse/TRAM-3502?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [TRAM-3502]: https://consensyssoftware.atlassian.net/browse/TRAM-3502?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Wires bearer-token access into the Buy/ramps path; mis-delegation would break Transak buy, but changes are localized to messenger setup and a dependency bump. > > **Overview** > Upgrades **`@metamask/ramps-controller`** to **^14.0.0** so the Buy widget can call the ramps API with an authenticated bearer token (required by the new controller contract). > > When **`getRampsServiceMessenger`** builds the child messenger, it now **delegates** `AuthenticationController:getBearerToken` from the root messenger into `RampsServiceMessenger`, so `RampsService` can mint tokens without the call failing at runtime. A unit test asserts that delegated call returns the token from the registered handler. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c7e989f. 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: Darius Costolas <10818970+meltingice1337@users.noreply.github.com> Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: Amitabh Aggarwal <aggarwal.amitabh@gmail.com>
1 parent cae6c60 commit 044726b

4 files changed

Lines changed: 24 additions & 14 deletions

File tree

app/core/Engine/messengers/ramps-service-messenger/ramps-service-messenger.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,19 @@ describe('getRampsServiceMessenger', () => {
2727

2828
expect(rampsServiceMessenger).toBeInstanceOf(Messenger);
2929
});
30+
31+
it('delegates AuthenticationController:getBearerToken so RampsService can call it', async () => {
32+
const rootMessenger: RootMessenger = getRootMessenger();
33+
rootMessenger.registerActionHandler(
34+
'AuthenticationController:getBearerToken',
35+
jest.fn().mockResolvedValue('test-bearer-token'),
36+
);
37+
const rampsServiceMessenger = getRampsServiceMessenger(rootMessenger);
38+
39+
const token = await rampsServiceMessenger.call(
40+
'AuthenticationController:getBearerToken',
41+
);
42+
43+
expect(token).toBe('test-bearer-token');
44+
});
3045
});

app/core/Engine/messengers/ramps-service-messenger/ramps-service-messenger.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type AllowedEvents = MessengerEvents<RampsServiceMessenger>;
1919
export function getRampsServiceMessenger(
2020
rootMessenger: RootMessenger,
2121
): RampsServiceMessenger {
22-
return new Messenger<
22+
const messenger = new Messenger<
2323
'RampsService',
2424
AllowedActions,
2525
AllowedEvents,
@@ -28,4 +28,10 @@ export function getRampsServiceMessenger(
2828
namespace: 'RampsService',
2929
parent: rootMessenger,
3030
});
31+
rootMessenger.delegate({
32+
actions: ['AuthenticationController:getBearerToken'],
33+
events: [],
34+
messenger,
35+
});
36+
return messenger;
3137
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@
322322
"@metamask/preinstalled-example-snap": "^0.7.2",
323323
"@metamask/profile-metrics-controller": "^3.1.0",
324324
"@metamask/profile-sync-controller": "^28.1.0",
325-
"@metamask/ramps-controller": "^13.3.1",
325+
"@metamask/ramps-controller": "^14.0.0",
326326
"@metamask/react-data-query": "^0.2.0",
327327
"@metamask/react-native-acm": "patch:@metamask/react-native-acm@npm%3A1.2.0#~/.yarn/patches/@metamask-react-native-acm-npm-1.2.0-944bf863eb.patch",
328328
"@metamask/react-native-actionsheet": "2.4.2",

yarn.lock

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9817,17 +9817,6 @@ __metadata:
98179817
languageName: node
98189818
linkType: hard
98199819

9820-
"@metamask/ramps-controller@npm:^13.3.1":
9821-
version: 13.3.1
9822-
resolution: "@metamask/ramps-controller@npm:13.3.1"
9823-
dependencies:
9824-
"@metamask/base-controller": "npm:^9.1.0"
9825-
"@metamask/controller-utils": "npm:^12.0.0"
9826-
"@metamask/messenger": "npm:^1.2.0"
9827-
checksum: 10/2ffbf48fce360be790c076e15f69cad6c07acc712376a8ac3c093fa69618a6624d5888f754360466ecdaff93d421a00e355d51c6d0c89b001c5a58d9f9ea40f4
9828-
languageName: node
9829-
linkType: hard
9830-
98319820
"@metamask/ramps-controller@npm:^14.0.0":
98329821
version: 14.0.0
98339822
resolution: "@metamask/ramps-controller@npm:14.0.0"
@@ -35551,7 +35540,7 @@ __metadata:
3555135540
"@metamask/profile-metrics-controller": "npm:^3.1.0"
3555235541
"@metamask/profile-sync-controller": "npm:^28.1.0"
3555335542
"@metamask/providers": "npm:^18.3.1"
35554-
"@metamask/ramps-controller": "npm:^13.3.1"
35543+
"@metamask/ramps-controller": "npm:^14.0.0"
3555535544
"@metamask/react-data-query": "npm:^0.2.0"
3555635545
"@metamask/react-native-acm": "patch:@metamask/react-native-acm@npm%3A1.2.0#~/.yarn/patches/@metamask-react-native-acm-npm-1.2.0-944bf863eb.patch"
3555735546
"@metamask/react-native-actionsheet": "npm:2.4.2"

0 commit comments

Comments
 (0)