Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/ramps-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add `preferredProvider` state and `setPreferredProvider()` method to RampsController ([#7617](https://github.com/MetaMask/core/pull/7617))

## [3.0.0]

### Added
Expand Down
84 changes: 83 additions & 1 deletion packages/ramps-controller/src/RampsController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {

import type { RampsControllerMessenger } from './RampsController';
import { RampsController } from './RampsController';
import type { Country, TokensResponse } from './RampsService';
import type { Country, TokensResponse, Provider } from './RampsService';
import type {
RampsServiceGetGeolocationAction,
RampsServiceGetCountriesAction,
Expand All @@ -24,6 +24,7 @@ describe('RampsController', () => {
expect(controller.state).toMatchInlineSnapshot(`
Object {
"eligibility": null,
"preferredProvider": null,
"requests": Object {},
"tokens": null,
"userRegion": null,
Expand All @@ -42,6 +43,7 @@ describe('RampsController', () => {
({ controller }) => {
expect(controller.state).toStrictEqual({
eligibility: null,
preferredProvider: null,
tokens: null,
userRegion: 'US',
requests: {},
Expand All @@ -55,6 +57,7 @@ describe('RampsController', () => {
expect(controller.state).toMatchInlineSnapshot(`
Object {
"eligibility": null,
"preferredProvider": null,
"requests": Object {},
"tokens": null,
"userRegion": null,
Expand Down Expand Up @@ -98,6 +101,7 @@ describe('RampsController', () => {
).toMatchInlineSnapshot(`
Object {
"eligibility": null,
"preferredProvider": null,
"requests": Object {},
"tokens": null,
"userRegion": null,
Expand All @@ -117,6 +121,7 @@ describe('RampsController', () => {
).toMatchInlineSnapshot(`
Object {
"eligibility": null,
"preferredProvider": null,
"tokens": null,
"userRegion": null,
}
Expand All @@ -135,6 +140,7 @@ describe('RampsController', () => {
).toMatchInlineSnapshot(`
Object {
"eligibility": null,
"preferredProvider": null,
"tokens": null,
"userRegion": null,
}
Expand All @@ -153,6 +159,7 @@ describe('RampsController', () => {
).toMatchInlineSnapshot(`
Object {
"eligibility": null,
"preferredProvider": null,
"requests": Object {},
"tokens": null,
"userRegion": null,
Expand Down Expand Up @@ -1090,6 +1097,81 @@ describe('RampsController', () => {
});
});

describe('setPreferredProvider', () => {
const mockProvider: Provider = {
id: '/providers/paypal-staging',
name: 'PayPal (Staging)',
environmentType: 'STAGING',
description: 'Test provider description',
hqAddress: '2211 N 1st St, San Jose, CA 95131',
links: [
{
name: 'Homepage',
url: 'https://www.paypal.com/us/home',
},
{
name: 'Terms of Service',
url: 'https://www.paypal.com/us/legalhub/cryptocurrencies-tnc',
},
{
name: 'Support',
url: 'https://www.paypal.com/us/cshelp',
},
],
logos: {
light: '/assets/providers/paypal_light.png',
dark: '/assets/providers/paypal_dark.png',
height: 24,
width: 77,
},
};

it('sets preferred provider', async () => {
await withController(({ controller }) => {
expect(controller.state.preferredProvider).toBeNull();

controller.setPreferredProvider(mockProvider);

expect(controller.state.preferredProvider).toStrictEqual(mockProvider);
});
});

it('clears preferred provider when set to null', async () => {
await withController(
{ options: { state: { preferredProvider: mockProvider } } },
({ controller }) => {
expect(controller.state.preferredProvider).toStrictEqual(
mockProvider,
);

controller.setPreferredProvider(null);

expect(controller.state.preferredProvider).toBeNull();
},
);
});

it('updates preferred provider when a new provider is set', async () => {
await withController(
{ options: { state: { preferredProvider: mockProvider } } },
({ controller }) => {
const newProvider: Provider = {
...mockProvider,
id: '/providers/ramp-network-staging',
name: 'Ramp Network (Staging)',
};

controller.setPreferredProvider(newProvider);

expect(controller.state.preferredProvider).toStrictEqual(newProvider);
expect(controller.state.preferredProvider?.id).toBe(
'/providers/ramp-network-staging',
);
},
);
});
});

describe('updateUserRegion with automatic eligibility', () => {
it('automatically fetches eligibility after getting user region', async () => {
await withController(async ({ controller, rootMessenger }) => {
Expand Down
31 changes: 30 additions & 1 deletion packages/ramps-controller/src/RampsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import { BaseController } from '@metamask/base-controller';
import type { Messenger } from '@metamask/messenger';
import type { Json } from '@metamask/utils';

import type { Country, Eligibility, TokensResponse } from './RampsService';
import type {
Country,
Eligibility,
TokensResponse,
Provider,
} from './RampsService';
import type {
RampsServiceGetGeolocationAction,
RampsServiceGetCountriesAction,
Expand Down Expand Up @@ -50,6 +55,11 @@ export type RampsControllerState = {
* Initially set via geolocation fetch, but can be manually changed by the user.
*/
userRegion: string | null;
/**
* The user's preferred provider.
* Can be manually set by the user.
*/
preferredProvider: Provider | null;
/**
* Eligibility information for the user's current region.
*/
Expand All @@ -76,6 +86,12 @@ const rampsControllerMetadata = {
includeInStateLogs: true,
usedInUi: true,
},
preferredProvider: {
persist: true,
includeInDebugSnapshot: true,
includeInStateLogs: true,
usedInUi: true,
},
eligibility: {
persist: true,
includeInDebugSnapshot: true,
Expand Down Expand Up @@ -107,6 +123,7 @@ const rampsControllerMetadata = {
export function getDefaultRampsControllerState(): RampsControllerState {
return {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {},
Expand Down Expand Up @@ -485,6 +502,18 @@ export class RampsController extends BaseController<
}
}

/**
* Sets the user's preferred provider.
* This allows users to set their preferred ramp provider.
*
* @param provider - The provider object to set.
*/
setPreferredProvider(provider: Provider | null): void {
this.update((state) => {
state.preferredProvider = provider;
});
}

/**
* Initializes the controller by fetching the user's region from geolocation.
* This should be called once at app startup to set up the initial region.
Expand Down
31 changes: 31 additions & 0 deletions packages/ramps-controller/src/RampsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,37 @@ export type Eligibility = {
global?: boolean;
};

/**
* Represents a provider link.
*/
export type ProviderLink = {
name: string;
url: string;
};

/**
* Represents provider logos.
*/
export type ProviderLogos = {
light: string;
dark: string;
height: number;
width: number;
};

/**
* Represents a ramp provider.
*/
export type Provider = {
id: string;
name: string;
environmentType: string;
description: string;
hqAddress: string;
links: ProviderLink[];
logos: ProviderLogos;
};

/**
* Represents a country returned from the regions/countries API.
*/
Expand Down
3 changes: 3 additions & 0 deletions packages/ramps-controller/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export type {
State,
Eligibility,
CountryPhone,
Provider,
ProviderLink,
ProviderLogos,
} from './RampsService';
export {
RampsService,
Expand Down
15 changes: 15 additions & 0 deletions packages/ramps-controller/src/selectors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('createRequestSelector', () => {
const state: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand Down Expand Up @@ -55,6 +56,7 @@ describe('createRequestSelector', () => {
const state: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand Down Expand Up @@ -88,6 +90,7 @@ describe('createRequestSelector', () => {
const state: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand Down Expand Up @@ -117,6 +120,7 @@ describe('createRequestSelector', () => {
const state: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {},
Expand Down Expand Up @@ -169,6 +173,7 @@ describe('createRequestSelector', () => {
const state: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand All @@ -194,6 +199,7 @@ describe('createRequestSelector', () => {
const state1: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand All @@ -208,6 +214,7 @@ describe('createRequestSelector', () => {
const state2: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand All @@ -234,6 +241,7 @@ describe('createRequestSelector', () => {
const state: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand Down Expand Up @@ -263,6 +271,7 @@ describe('createRequestSelector', () => {
const state: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand Down Expand Up @@ -291,6 +300,7 @@ describe('createRequestSelector', () => {
const loadingState: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand All @@ -307,6 +317,7 @@ describe('createRequestSelector', () => {
const successState: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand All @@ -331,6 +342,7 @@ describe('createRequestSelector', () => {
const successState: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand All @@ -346,6 +358,7 @@ describe('createRequestSelector', () => {
const errorState: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand Down Expand Up @@ -376,6 +389,7 @@ describe('createRequestSelector', () => {
const state: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand Down Expand Up @@ -410,6 +424,7 @@ describe('createRequestSelector', () => {
const state: TestRootState = {
ramps: {
userRegion: null,
preferredProvider: null,
eligibility: null,
tokens: null,
requests: {
Expand Down
Loading