@metamask/ramps-controller 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,7 +23,7 @@ export const controllerName = 'RampsController';
23
23
  * The metadata for each property in {@link RampsControllerState}.
24
24
  */
25
25
  const rampsControllerMetadata = {
26
- geolocation: {
26
+ userRegion: {
27
27
  persist: true,
28
28
  includeInDebugSnapshot: true,
29
29
  includeInStateLogs: true,
@@ -35,6 +35,12 @@ const rampsControllerMetadata = {
35
35
  includeInStateLogs: true,
36
36
  usedInUi: true,
37
37
  },
38
+ tokens: {
39
+ persist: true,
40
+ includeInDebugSnapshot: true,
41
+ includeInStateLogs: true,
42
+ usedInUi: true,
43
+ },
38
44
  requests: {
39
45
  persist: false,
40
46
  includeInDebugSnapshot: true,
@@ -52,8 +58,9 @@ const rampsControllerMetadata = {
52
58
  */
53
59
  export function getDefaultRampsControllerState() {
54
60
  return {
55
- geolocation: null,
61
+ userRegion: null,
56
62
  eligibility: null,
63
+ tokens: null,
57
64
  requests: {},
58
65
  };
59
66
  }
@@ -190,36 +197,97 @@ export class RampsController extends BaseController {
190
197
  return this.state.requests[cacheKey];
191
198
  }
192
199
  /**
193
- * Updates the user's geolocation and eligibility.
200
+ * Updates the user's region by fetching geolocation and eligibility.
194
201
  * This method calls the RampsService to get the geolocation,
195
202
  * then automatically fetches eligibility for that region.
196
203
  *
197
204
  * @param options - Options for cache behavior.
198
- * @returns The geolocation string.
205
+ * @returns The user region string.
199
206
  */
200
- async updateGeolocation(options) {
201
- const cacheKey = createCacheKey('updateGeolocation', []);
202
- const geolocation = await this.executeRequest(cacheKey, async () => {
207
+ async updateUserRegion(options) {
208
+ const cacheKey = createCacheKey('updateUserRegion', []);
209
+ const userRegion = await this.executeRequest(cacheKey, async () => {
203
210
  const result = await this.messenger.call('RampsService:getGeolocation');
204
211
  return result;
205
212
  }, options);
213
+ const normalizedRegion = userRegion
214
+ ? userRegion.toLowerCase().trim()
215
+ : userRegion;
206
216
  this.update((state) => {
207
- state.geolocation = geolocation;
217
+ state.userRegion = normalizedRegion;
218
+ state.tokens = null;
208
219
  });
209
- if (geolocation) {
220
+ if (normalizedRegion) {
210
221
  try {
211
- await this.updateEligibility(geolocation, options);
222
+ await this.updateEligibility(normalizedRegion, options);
212
223
  }
213
224
  catch {
214
- // Eligibility fetch failed, but geolocation was successfully fetched and cached.
215
- // Don't let eligibility errors prevent geolocation state from being updated.
216
- // Clear eligibility state to avoid showing stale data from a previous location.
217
225
  this.update((state) => {
218
- state.eligibility = null;
226
+ const currentUserRegion = state.userRegion?.toLowerCase().trim();
227
+ if (currentUserRegion === normalizedRegion) {
228
+ state.eligibility = null;
229
+ state.tokens = null;
230
+ }
219
231
  });
220
232
  }
221
233
  }
222
- return geolocation;
234
+ return normalizedRegion;
235
+ }
236
+ /**
237
+ * Sets the user's region manually (without fetching geolocation).
238
+ * This allows users to override the detected region.
239
+ *
240
+ * @param region - The region code to set (e.g., "US-CA").
241
+ * @param options - Options for cache behavior when fetching eligibility.
242
+ * @returns The eligibility information for the region.
243
+ */
244
+ async setUserRegion(region, options) {
245
+ const normalizedRegion = region.toLowerCase().trim();
246
+ this.update((state) => {
247
+ state.userRegion = normalizedRegion;
248
+ state.tokens = null;
249
+ });
250
+ try {
251
+ return await this.updateEligibility(normalizedRegion, options);
252
+ }
253
+ catch (error) {
254
+ // Eligibility fetch failed, but user region was successfully set.
255
+ // Don't let eligibility errors prevent user region state from being updated.
256
+ // Clear eligibility state to avoid showing stale data from a previous location.
257
+ // Only clear if the region still matches to avoid race conditions where a newer
258
+ // region change has already succeeded.
259
+ this.update((state) => {
260
+ const currentUserRegion = state.userRegion?.toLowerCase().trim();
261
+ if (currentUserRegion === normalizedRegion) {
262
+ state.eligibility = null;
263
+ state.tokens = null;
264
+ }
265
+ });
266
+ throw error;
267
+ }
268
+ }
269
+ /**
270
+ * Initializes the controller by fetching the user's region from geolocation.
271
+ * This should be called once at app startup to set up the initial region.
272
+ * After the region is set and eligibility is determined, tokens are fetched
273
+ * and saved to state.
274
+ *
275
+ * @param options - Options for cache behavior.
276
+ * @returns Promise that resolves when initialization is complete.
277
+ */
278
+ async init(options) {
279
+ const userRegion = await this.updateUserRegion(options).catch(() => {
280
+ // User region fetch failed - error state will be available via selectors
281
+ return null;
282
+ });
283
+ if (userRegion) {
284
+ try {
285
+ await this.getTokens(userRegion, 'buy', options);
286
+ }
287
+ catch {
288
+ // Token fetch failed - error state will be available via selectors
289
+ }
290
+ }
223
291
  }
224
292
  /**
225
293
  * Updates the eligibility information for a given region.
@@ -235,8 +303,8 @@ export class RampsController extends BaseController {
235
303
  return this.messenger.call('RampsService:getEligibility', normalizedIsoCode);
236
304
  }, options);
237
305
  this.update((state) => {
238
- if (state.geolocation === null ||
239
- state.geolocation.toLowerCase().trim() === normalizedIsoCode) {
306
+ const userRegion = state.userRegion?.toLowerCase().trim();
307
+ if (userRegion === undefined || userRegion === normalizedIsoCode) {
240
308
  state.eligibility = eligibility;
241
309
  }
242
310
  });
@@ -255,6 +323,33 @@ export class RampsController extends BaseController {
255
323
  return this.messenger.call('RampsService:getCountries', action);
256
324
  }, options);
257
325
  }
326
+ /**
327
+ * Fetches the list of available tokens for a given region and action.
328
+ * The tokens are saved in the controller state once fetched.
329
+ *
330
+ * @param region - The region code (e.g., "us", "fr", "us-ny"). If not provided, uses the user's region from controller state.
331
+ * @param action - The ramp action type ('buy' or 'sell').
332
+ * @param options - Options for cache behavior.
333
+ * @returns The tokens response containing topTokens and allTokens.
334
+ */
335
+ async getTokens(region, action = 'buy', options) {
336
+ const regionToUse = region ?? this.state.userRegion;
337
+ if (!regionToUse) {
338
+ throw new Error('Region is required. Either provide a region parameter or ensure userRegion is set in controller state.');
339
+ }
340
+ const normalizedRegion = regionToUse.toLowerCase().trim();
341
+ const cacheKey = createCacheKey('getTokens', [normalizedRegion, action]);
342
+ const tokens = await this.executeRequest(cacheKey, async () => {
343
+ return this.messenger.call('RampsService:getTokens', normalizedRegion, action);
344
+ }, options);
345
+ this.update((state) => {
346
+ const userRegion = state.userRegion?.toLowerCase().trim();
347
+ if (userRegion === undefined || userRegion === normalizedRegion) {
348
+ state.tokens = tokens;
349
+ }
350
+ });
351
+ return tokens;
352
+ }
258
353
  }
259
354
  _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheMaxSize = new WeakMap(), _RampsController_pendingRequests = new WeakMap(), _RampsController_instances = new WeakSet(), _RampsController_removeRequestState = function _RampsController_removeRequestState(cacheKey) {
260
355
  this.update((state) => {
@@ -1 +1 @@
1
- {"version":3,"file":"RampsController.mjs","sourceRoot":"","sources":["../src/RampsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport type { Json } from '@metamask/utils';\n\nimport type { Country, Eligibility } from './RampsService';\nimport type {\n RampsServiceGetGeolocationAction,\n RampsServiceGetCountriesAction,\n RampsServiceGetEligibilityAction,\n} from './RampsService-method-action-types';\nimport type {\n RequestCache as RequestCacheType,\n RequestState,\n ExecuteRequestOptions,\n PendingRequest,\n} from './RequestCache';\nimport {\n DEFAULT_REQUEST_CACHE_TTL,\n DEFAULT_REQUEST_CACHE_MAX_SIZE,\n createCacheKey,\n isCacheExpired,\n createLoadingState,\n createSuccessState,\n createErrorState,\n} from './RequestCache';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link RampsController}, used to namespace the\n * controller's actions and events and to namespace the controller's state data\n * when composed with other controllers.\n */\nexport const controllerName = 'RampsController';\n\n// === STATE ===\n\n/**\n * Describes the shape of the state object for {@link RampsController}.\n */\nexport type RampsControllerState = {\n /**\n * The user's country code determined by geolocation.\n */\n geolocation: string | null;\n /**\n * Eligibility information for the user's current region.\n */\n eligibility: Eligibility | null;\n /**\n * Cache of request states, keyed by cache key.\n * This stores loading, success, and error states for API requests.\n */\n requests: RequestCacheType;\n};\n\n/**\n * The metadata for each property in {@link RampsControllerState}.\n */\nconst rampsControllerMetadata = {\n geolocation: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: true,\n },\n eligibility: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: true,\n },\n requests: {\n persist: false,\n includeInDebugSnapshot: true,\n includeInStateLogs: false,\n usedInUi: true,\n },\n} satisfies StateMetadata<RampsControllerState>;\n\n/**\n * Constructs the default {@link RampsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link RampsController} state.\n */\nexport function getDefaultRampsControllerState(): RampsControllerState {\n return {\n geolocation: null,\n eligibility: null,\n requests: {},\n };\n}\n\n// === MESSENGER ===\n\n/**\n * Retrieves the state of the {@link RampsController}.\n */\nexport type RampsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n RampsControllerState\n>;\n\n/**\n * Actions that {@link RampsControllerMessenger} exposes to other consumers.\n */\nexport type RampsControllerActions = RampsControllerGetStateAction;\n\n/**\n * Actions from other messengers that {@link RampsController} calls.\n */\ntype AllowedActions =\n | RampsServiceGetGeolocationAction\n | RampsServiceGetCountriesAction\n | RampsServiceGetEligibilityAction;\n\n/**\n * Published when the state of {@link RampsController} changes.\n */\nexport type RampsControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n RampsControllerState\n>;\n\n/**\n * Events that {@link RampsControllerMessenger} exposes to other consumers.\n */\nexport type RampsControllerEvents = RampsControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link RampsController} subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger restricted to actions and events accessed by\n * {@link RampsController}.\n */\nexport type RampsControllerMessenger = Messenger<\n typeof controllerName,\n RampsControllerActions | AllowedActions,\n RampsControllerEvents | AllowedEvents\n>;\n\n/**\n * Configuration options for the RampsController.\n */\nexport type RampsControllerOptions = {\n /** The messenger suited for this controller. */\n messenger: RampsControllerMessenger;\n /** The desired state with which to initialize this controller. */\n state?: Partial<RampsControllerState>;\n /** Time to live for cached requests in milliseconds. Defaults to 15 minutes. */\n requestCacheTTL?: number;\n /** Maximum number of entries in the request cache. Defaults to 250. */\n requestCacheMaxSize?: number;\n};\n\n// === CONTROLLER DEFINITION ===\n\n/**\n * Manages cryptocurrency on/off ramps functionality.\n */\nexport class RampsController extends BaseController<\n typeof controllerName,\n RampsControllerState,\n RampsControllerMessenger\n> {\n /**\n * Default TTL for cached requests.\n */\n readonly #requestCacheTTL: number;\n\n /**\n * Maximum number of entries in the request cache.\n */\n readonly #requestCacheMaxSize: number;\n\n /**\n * Map of pending requests for deduplication.\n * Key is the cache key, value is the pending request with abort controller.\n */\n readonly #pendingRequests: Map<string, PendingRequest> = new Map();\n\n /**\n * Constructs a new {@link RampsController}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this controller.\n * @param args.state - The desired state with which to initialize this\n * controller. Missing properties will be filled in with defaults.\n * @param args.requestCacheTTL - Time to live for cached requests in milliseconds.\n * @param args.requestCacheMaxSize - Maximum number of entries in the request cache.\n */\n constructor({\n messenger,\n state = {},\n requestCacheTTL = DEFAULT_REQUEST_CACHE_TTL,\n requestCacheMaxSize = DEFAULT_REQUEST_CACHE_MAX_SIZE,\n }: RampsControllerOptions) {\n super({\n messenger,\n metadata: rampsControllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultRampsControllerState(),\n ...state,\n // Always reset requests cache on initialization (non-persisted)\n requests: {},\n },\n });\n\n this.#requestCacheTTL = requestCacheTTL;\n this.#requestCacheMaxSize = requestCacheMaxSize;\n }\n\n /**\n * Executes a request with caching and deduplication.\n *\n * If a request with the same cache key is already in flight, returns the\n * existing promise. If valid cached data exists, returns it without making\n * a new request.\n *\n * @param cacheKey - Unique identifier for this request.\n * @param fetcher - Function that performs the actual fetch. Receives an AbortSignal.\n * @param options - Options for cache behavior.\n * @returns The result of the request.\n */\n async executeRequest<TResult>(\n cacheKey: string,\n fetcher: (signal: AbortSignal) => Promise<TResult>,\n options?: ExecuteRequestOptions,\n ): Promise<TResult> {\n const ttl = options?.ttl ?? this.#requestCacheTTL;\n\n // Check for existing pending request - join it instead of making a duplicate\n const pending = this.#pendingRequests.get(cacheKey);\n if (pending) {\n return pending.promise as Promise<TResult>;\n }\n\n // Check cache validity (unless force refresh)\n if (!options?.forceRefresh) {\n const cached = this.state.requests[cacheKey];\n if (cached && !isCacheExpired(cached, ttl)) {\n return cached.data as TResult;\n }\n }\n\n // Create abort controller for this request\n const abortController = new AbortController();\n const lastFetchedAt = Date.now();\n\n // Update state to loading\n this.#updateRequestState(cacheKey, createLoadingState());\n\n // Create the fetch promise\n const promise = (async (): Promise<TResult> => {\n try {\n const data = await fetcher(abortController.signal);\n\n // Don't update state if aborted\n if (abortController.signal.aborted) {\n throw new Error('Request was aborted');\n }\n\n this.#updateRequestState(\n cacheKey,\n createSuccessState(data as Json, lastFetchedAt),\n );\n return data;\n } catch (error) {\n // Don't update state if aborted\n if (abortController.signal.aborted) {\n throw error;\n }\n\n const errorMessage = (error as Error)?.message;\n\n this.#updateRequestState(\n cacheKey,\n createErrorState(errorMessage ?? 'Unknown error', lastFetchedAt),\n );\n throw error;\n } finally {\n // Only delete if this is still our entry (not replaced by a new request)\n const currentPending = this.#pendingRequests.get(cacheKey);\n if (currentPending?.abortController === abortController) {\n this.#pendingRequests.delete(cacheKey);\n }\n }\n })();\n\n // Store pending request for deduplication\n this.#pendingRequests.set(cacheKey, { promise, abortController });\n\n return promise;\n }\n\n /**\n * Aborts a pending request if one exists.\n *\n * @param cacheKey - The cache key of the request to abort.\n * @returns True if a request was aborted.\n */\n abortRequest(cacheKey: string): boolean {\n const pending = this.#pendingRequests.get(cacheKey);\n if (pending) {\n pending.abortController.abort();\n this.#pendingRequests.delete(cacheKey);\n this.#removeRequestState(cacheKey);\n return true;\n }\n return false;\n }\n\n /**\n * Removes a request state from the cache.\n *\n * @param cacheKey - The cache key to remove.\n */\n #removeRequestState(cacheKey: string): void {\n this.update((state) => {\n const requests = state.requests as unknown as Record<\n string,\n RequestState | undefined\n >;\n delete requests[cacheKey];\n });\n }\n\n /**\n * Gets the state of a specific cached request.\n *\n * @param cacheKey - The cache key to look up.\n * @returns The request state, or undefined if not cached.\n */\n getRequestState(cacheKey: string): RequestState | undefined {\n return this.state.requests[cacheKey];\n }\n\n /**\n * Updates the state for a specific request.\n *\n * @param cacheKey - The cache key.\n * @param requestState - The new state for the request.\n */\n #updateRequestState(cacheKey: string, requestState: RequestState): void {\n const maxSize = this.#requestCacheMaxSize;\n\n this.update((state) => {\n const requests = state.requests as unknown as Record<\n string,\n RequestState | undefined\n >;\n requests[cacheKey] = requestState;\n\n // Evict oldest entries if cache exceeds max size\n const keys = Object.keys(requests);\n\n if (keys.length > maxSize) {\n // Sort by timestamp (oldest first)\n const sortedKeys = keys.sort((a, b) => {\n const aTime = requests[a]?.timestamp ?? 0;\n const bTime = requests[b]?.timestamp ?? 0;\n return aTime - bTime;\n });\n\n // Remove oldest entries until we're under the limit\n const entriesToRemove = keys.length - maxSize;\n for (let i = 0; i < entriesToRemove; i++) {\n const keyToRemove = sortedKeys[i];\n if (keyToRemove) {\n delete requests[keyToRemove];\n }\n }\n }\n });\n }\n\n /**\n * Updates the user's geolocation and eligibility.\n * This method calls the RampsService to get the geolocation,\n * then automatically fetches eligibility for that region.\n *\n * @param options - Options for cache behavior.\n * @returns The geolocation string.\n */\n async updateGeolocation(options?: ExecuteRequestOptions): Promise<string> {\n const cacheKey = createCacheKey('updateGeolocation', []);\n\n const geolocation = await this.executeRequest(\n cacheKey,\n async () => {\n const result = await this.messenger.call('RampsService:getGeolocation');\n return result;\n },\n options,\n );\n\n this.update((state) => {\n state.geolocation = geolocation;\n });\n\n if (geolocation) {\n try {\n await this.updateEligibility(geolocation, options);\n } catch {\n // Eligibility fetch failed, but geolocation was successfully fetched and cached.\n // Don't let eligibility errors prevent geolocation state from being updated.\n // Clear eligibility state to avoid showing stale data from a previous location.\n this.update((state) => {\n state.eligibility = null;\n });\n }\n }\n\n return geolocation;\n }\n\n /**\n * Updates the eligibility information for a given region.\n *\n * @param isoCode - The ISO code for the region (e.g., \"us\", \"fr\", \"us-ny\").\n * @param options - Options for cache behavior.\n * @returns The eligibility information.\n */\n async updateEligibility(\n isoCode: string,\n options?: ExecuteRequestOptions,\n ): Promise<Eligibility> {\n const normalizedIsoCode = isoCode.toLowerCase().trim();\n const cacheKey = createCacheKey('updateEligibility', [normalizedIsoCode]);\n\n const eligibility = await this.executeRequest(\n cacheKey,\n async () => {\n return this.messenger.call(\n 'RampsService:getEligibility',\n normalizedIsoCode,\n );\n },\n options,\n );\n\n this.update((state) => {\n if (\n state.geolocation === null ||\n state.geolocation.toLowerCase().trim() === normalizedIsoCode\n ) {\n state.eligibility = eligibility;\n }\n });\n\n return eligibility;\n }\n\n /**\n * Fetches the list of supported countries for a given ramp action.\n *\n * @param action - The ramp action type ('buy' or 'sell').\n * @param options - Options for cache behavior.\n * @returns An array of countries with their eligibility information.\n */\n async getCountries(\n action: 'buy' | 'sell' = 'buy',\n options?: ExecuteRequestOptions,\n ): Promise<Country[]> {\n const cacheKey = createCacheKey('getCountries', [action]);\n\n return this.executeRequest(\n cacheKey,\n async () => {\n return this.messenger.call('RampsService:getCountries', action);\n },\n options,\n );\n }\n}\n"]}
1
+ {"version":3,"file":"RampsController.mjs","sourceRoot":"","sources":["../src/RampsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport type { Json } from '@metamask/utils';\n\nimport type { Country, Eligibility, TokensResponse } from './RampsService';\nimport type {\n RampsServiceGetGeolocationAction,\n RampsServiceGetCountriesAction,\n RampsServiceGetEligibilityAction,\n RampsServiceGetTokensAction,\n} from './RampsService-method-action-types';\nimport type {\n RequestCache as RequestCacheType,\n RequestState,\n ExecuteRequestOptions,\n PendingRequest,\n} from './RequestCache';\nimport {\n DEFAULT_REQUEST_CACHE_TTL,\n DEFAULT_REQUEST_CACHE_MAX_SIZE,\n createCacheKey,\n isCacheExpired,\n createLoadingState,\n createSuccessState,\n createErrorState,\n} from './RequestCache';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link RampsController}, used to namespace the\n * controller's actions and events and to namespace the controller's state data\n * when composed with other controllers.\n */\nexport const controllerName = 'RampsController';\n\n// === STATE ===\n\n/**\n * Describes the shape of the state object for {@link RampsController}.\n */\nexport type RampsControllerState = {\n /**\n * The user's selected region code (e.g., \"US-CA\").\n * Initially set via geolocation fetch, but can be manually changed by the user.\n */\n userRegion: string | null;\n /**\n * Eligibility information for the user's current region.\n */\n eligibility: Eligibility | null;\n /**\n * Tokens fetched for the current region and action.\n * Contains topTokens and allTokens arrays.\n */\n tokens: TokensResponse | null;\n /**\n * Cache of request states, keyed by cache key.\n * This stores loading, success, and error states for API requests.\n */\n requests: RequestCacheType;\n};\n\n/**\n * The metadata for each property in {@link RampsControllerState}.\n */\nconst rampsControllerMetadata = {\n userRegion: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: true,\n },\n eligibility: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: true,\n },\n tokens: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: true,\n },\n requests: {\n persist: false,\n includeInDebugSnapshot: true,\n includeInStateLogs: false,\n usedInUi: true,\n },\n} satisfies StateMetadata<RampsControllerState>;\n\n/**\n * Constructs the default {@link RampsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link RampsController} state.\n */\nexport function getDefaultRampsControllerState(): RampsControllerState {\n return {\n userRegion: null,\n eligibility: null,\n tokens: null,\n requests: {},\n };\n}\n\n// === MESSENGER ===\n\n/**\n * Retrieves the state of the {@link RampsController}.\n */\nexport type RampsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n RampsControllerState\n>;\n\n/**\n * Actions that {@link RampsControllerMessenger} exposes to other consumers.\n */\nexport type RampsControllerActions = RampsControllerGetStateAction;\n\n/**\n * Actions from other messengers that {@link RampsController} calls.\n */\ntype AllowedActions =\n | RampsServiceGetGeolocationAction\n | RampsServiceGetCountriesAction\n | RampsServiceGetEligibilityAction\n | RampsServiceGetTokensAction;\n\n/**\n * Published when the state of {@link RampsController} changes.\n */\nexport type RampsControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n RampsControllerState\n>;\n\n/**\n * Events that {@link RampsControllerMessenger} exposes to other consumers.\n */\nexport type RampsControllerEvents = RampsControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link RampsController} subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger restricted to actions and events accessed by\n * {@link RampsController}.\n */\nexport type RampsControllerMessenger = Messenger<\n typeof controllerName,\n RampsControllerActions | AllowedActions,\n RampsControllerEvents | AllowedEvents\n>;\n\n/**\n * Configuration options for the RampsController.\n */\nexport type RampsControllerOptions = {\n /** The messenger suited for this controller. */\n messenger: RampsControllerMessenger;\n /** The desired state with which to initialize this controller. */\n state?: Partial<RampsControllerState>;\n /** Time to live for cached requests in milliseconds. Defaults to 15 minutes. */\n requestCacheTTL?: number;\n /** Maximum number of entries in the request cache. Defaults to 250. */\n requestCacheMaxSize?: number;\n};\n\n// === CONTROLLER DEFINITION ===\n\n/**\n * Manages cryptocurrency on/off ramps functionality.\n */\nexport class RampsController extends BaseController<\n typeof controllerName,\n RampsControllerState,\n RampsControllerMessenger\n> {\n /**\n * Default TTL for cached requests.\n */\n readonly #requestCacheTTL: number;\n\n /**\n * Maximum number of entries in the request cache.\n */\n readonly #requestCacheMaxSize: number;\n\n /**\n * Map of pending requests for deduplication.\n * Key is the cache key, value is the pending request with abort controller.\n */\n readonly #pendingRequests: Map<string, PendingRequest> = new Map();\n\n /**\n * Constructs a new {@link RampsController}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this controller.\n * @param args.state - The desired state with which to initialize this\n * controller. Missing properties will be filled in with defaults.\n * @param args.requestCacheTTL - Time to live for cached requests in milliseconds.\n * @param args.requestCacheMaxSize - Maximum number of entries in the request cache.\n */\n constructor({\n messenger,\n state = {},\n requestCacheTTL = DEFAULT_REQUEST_CACHE_TTL,\n requestCacheMaxSize = DEFAULT_REQUEST_CACHE_MAX_SIZE,\n }: RampsControllerOptions) {\n super({\n messenger,\n metadata: rampsControllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultRampsControllerState(),\n ...state,\n // Always reset requests cache on initialization (non-persisted)\n requests: {},\n },\n });\n\n this.#requestCacheTTL = requestCacheTTL;\n this.#requestCacheMaxSize = requestCacheMaxSize;\n }\n\n /**\n * Executes a request with caching and deduplication.\n *\n * If a request with the same cache key is already in flight, returns the\n * existing promise. If valid cached data exists, returns it without making\n * a new request.\n *\n * @param cacheKey - Unique identifier for this request.\n * @param fetcher - Function that performs the actual fetch. Receives an AbortSignal.\n * @param options - Options for cache behavior.\n * @returns The result of the request.\n */\n async executeRequest<TResult>(\n cacheKey: string,\n fetcher: (signal: AbortSignal) => Promise<TResult>,\n options?: ExecuteRequestOptions,\n ): Promise<TResult> {\n const ttl = options?.ttl ?? this.#requestCacheTTL;\n\n // Check for existing pending request - join it instead of making a duplicate\n const pending = this.#pendingRequests.get(cacheKey);\n if (pending) {\n return pending.promise as Promise<TResult>;\n }\n\n // Check cache validity (unless force refresh)\n if (!options?.forceRefresh) {\n const cached = this.state.requests[cacheKey];\n if (cached && !isCacheExpired(cached, ttl)) {\n return cached.data as TResult;\n }\n }\n\n // Create abort controller for this request\n const abortController = new AbortController();\n const lastFetchedAt = Date.now();\n\n // Update state to loading\n this.#updateRequestState(cacheKey, createLoadingState());\n\n // Create the fetch promise\n const promise = (async (): Promise<TResult> => {\n try {\n const data = await fetcher(abortController.signal);\n\n // Don't update state if aborted\n if (abortController.signal.aborted) {\n throw new Error('Request was aborted');\n }\n\n this.#updateRequestState(\n cacheKey,\n createSuccessState(data as Json, lastFetchedAt),\n );\n return data;\n } catch (error) {\n // Don't update state if aborted\n if (abortController.signal.aborted) {\n throw error;\n }\n\n const errorMessage = (error as Error)?.message;\n\n this.#updateRequestState(\n cacheKey,\n createErrorState(errorMessage ?? 'Unknown error', lastFetchedAt),\n );\n throw error;\n } finally {\n // Only delete if this is still our entry (not replaced by a new request)\n const currentPending = this.#pendingRequests.get(cacheKey);\n if (currentPending?.abortController === abortController) {\n this.#pendingRequests.delete(cacheKey);\n }\n }\n })();\n\n // Store pending request for deduplication\n this.#pendingRequests.set(cacheKey, { promise, abortController });\n\n return promise;\n }\n\n /**\n * Aborts a pending request if one exists.\n *\n * @param cacheKey - The cache key of the request to abort.\n * @returns True if a request was aborted.\n */\n abortRequest(cacheKey: string): boolean {\n const pending = this.#pendingRequests.get(cacheKey);\n if (pending) {\n pending.abortController.abort();\n this.#pendingRequests.delete(cacheKey);\n this.#removeRequestState(cacheKey);\n return true;\n }\n return false;\n }\n\n /**\n * Removes a request state from the cache.\n *\n * @param cacheKey - The cache key to remove.\n */\n #removeRequestState(cacheKey: string): void {\n this.update((state) => {\n const requests = state.requests as unknown as Record<\n string,\n RequestState | undefined\n >;\n delete requests[cacheKey];\n });\n }\n\n /**\n * Gets the state of a specific cached request.\n *\n * @param cacheKey - The cache key to look up.\n * @returns The request state, or undefined if not cached.\n */\n getRequestState(cacheKey: string): RequestState | undefined {\n return this.state.requests[cacheKey];\n }\n\n /**\n * Updates the state for a specific request.\n *\n * @param cacheKey - The cache key.\n * @param requestState - The new state for the request.\n */\n #updateRequestState(cacheKey: string, requestState: RequestState): void {\n const maxSize = this.#requestCacheMaxSize;\n\n this.update((state) => {\n const requests = state.requests as unknown as Record<\n string,\n RequestState | undefined\n >;\n requests[cacheKey] = requestState;\n\n // Evict oldest entries if cache exceeds max size\n const keys = Object.keys(requests);\n\n if (keys.length > maxSize) {\n // Sort by timestamp (oldest first)\n const sortedKeys = keys.sort((a, b) => {\n const aTime = requests[a]?.timestamp ?? 0;\n const bTime = requests[b]?.timestamp ?? 0;\n return aTime - bTime;\n });\n\n // Remove oldest entries until we're under the limit\n const entriesToRemove = keys.length - maxSize;\n for (let i = 0; i < entriesToRemove; i++) {\n const keyToRemove = sortedKeys[i];\n if (keyToRemove) {\n delete requests[keyToRemove];\n }\n }\n }\n });\n }\n\n /**\n * Updates the user's region by fetching geolocation and eligibility.\n * This method calls the RampsService to get the geolocation,\n * then automatically fetches eligibility for that region.\n *\n * @param options - Options for cache behavior.\n * @returns The user region string.\n */\n async updateUserRegion(options?: ExecuteRequestOptions): Promise<string> {\n const cacheKey = createCacheKey('updateUserRegion', []);\n\n const userRegion = await this.executeRequest(\n cacheKey,\n async () => {\n const result = await this.messenger.call('RampsService:getGeolocation');\n return result;\n },\n options,\n );\n\n const normalizedRegion = userRegion\n ? userRegion.toLowerCase().trim()\n : userRegion;\n\n this.update((state) => {\n state.userRegion = normalizedRegion;\n state.tokens = null;\n });\n\n if (normalizedRegion) {\n try {\n await this.updateEligibility(normalizedRegion, options);\n } catch {\n this.update((state) => {\n const currentUserRegion = state.userRegion?.toLowerCase().trim();\n if (currentUserRegion === normalizedRegion) {\n state.eligibility = null;\n state.tokens = null;\n }\n });\n }\n }\n\n return normalizedRegion;\n }\n\n /**\n * Sets the user's region manually (without fetching geolocation).\n * This allows users to override the detected region.\n *\n * @param region - The region code to set (e.g., \"US-CA\").\n * @param options - Options for cache behavior when fetching eligibility.\n * @returns The eligibility information for the region.\n */\n async setUserRegion(\n region: string,\n options?: ExecuteRequestOptions,\n ): Promise<Eligibility> {\n const normalizedRegion = region.toLowerCase().trim();\n\n this.update((state) => {\n state.userRegion = normalizedRegion;\n state.tokens = null;\n });\n\n try {\n return await this.updateEligibility(normalizedRegion, options);\n } catch (error) {\n // Eligibility fetch failed, but user region was successfully set.\n // Don't let eligibility errors prevent user region state from being updated.\n // Clear eligibility state to avoid showing stale data from a previous location.\n // Only clear if the region still matches to avoid race conditions where a newer\n // region change has already succeeded.\n this.update((state) => {\n const currentUserRegion = state.userRegion?.toLowerCase().trim();\n if (currentUserRegion === normalizedRegion) {\n state.eligibility = null;\n state.tokens = null;\n }\n });\n throw error;\n }\n }\n\n /**\n * Initializes the controller by fetching the user's region from geolocation.\n * This should be called once at app startup to set up the initial region.\n * After the region is set and eligibility is determined, tokens are fetched\n * and saved to state.\n *\n * @param options - Options for cache behavior.\n * @returns Promise that resolves when initialization is complete.\n */\n async init(options?: ExecuteRequestOptions): Promise<void> {\n const userRegion = await this.updateUserRegion(options).catch(() => {\n // User region fetch failed - error state will be available via selectors\n return null;\n });\n\n if (userRegion) {\n try {\n await this.getTokens(userRegion, 'buy', options);\n } catch {\n // Token fetch failed - error state will be available via selectors\n }\n }\n }\n\n /**\n * Updates the eligibility information for a given region.\n *\n * @param isoCode - The ISO code for the region (e.g., \"us\", \"fr\", \"us-ny\").\n * @param options - Options for cache behavior.\n * @returns The eligibility information.\n */\n async updateEligibility(\n isoCode: string,\n options?: ExecuteRequestOptions,\n ): Promise<Eligibility> {\n const normalizedIsoCode = isoCode.toLowerCase().trim();\n const cacheKey = createCacheKey('updateEligibility', [normalizedIsoCode]);\n\n const eligibility = await this.executeRequest(\n cacheKey,\n async () => {\n return this.messenger.call(\n 'RampsService:getEligibility',\n normalizedIsoCode,\n );\n },\n options,\n );\n\n this.update((state) => {\n const userRegion = state.userRegion?.toLowerCase().trim();\n\n if (userRegion === undefined || userRegion === normalizedIsoCode) {\n state.eligibility = eligibility;\n }\n });\n\n return eligibility;\n }\n\n /**\n * Fetches the list of supported countries for a given ramp action.\n *\n * @param action - The ramp action type ('buy' or 'sell').\n * @param options - Options for cache behavior.\n * @returns An array of countries with their eligibility information.\n */\n async getCountries(\n action: 'buy' | 'sell' = 'buy',\n options?: ExecuteRequestOptions,\n ): Promise<Country[]> {\n const cacheKey = createCacheKey('getCountries', [action]);\n\n return this.executeRequest(\n cacheKey,\n async () => {\n return this.messenger.call('RampsService:getCountries', action);\n },\n options,\n );\n }\n\n /**\n * Fetches the list of available tokens for a given region and action.\n * The tokens are saved in the controller state once fetched.\n *\n * @param region - The region code (e.g., \"us\", \"fr\", \"us-ny\"). If not provided, uses the user's region from controller state.\n * @param action - The ramp action type ('buy' or 'sell').\n * @param options - Options for cache behavior.\n * @returns The tokens response containing topTokens and allTokens.\n */\n async getTokens(\n region?: string,\n action: 'buy' | 'sell' = 'buy',\n options?: ExecuteRequestOptions,\n ): Promise<TokensResponse> {\n const regionToUse = region ?? this.state.userRegion;\n\n if (!regionToUse) {\n throw new Error(\n 'Region is required. Either provide a region parameter or ensure userRegion is set in controller state.',\n );\n }\n\n const normalizedRegion = regionToUse.toLowerCase().trim();\n const cacheKey = createCacheKey('getTokens', [normalizedRegion, action]);\n\n const tokens = await this.executeRequest(\n cacheKey,\n async () => {\n return this.messenger.call(\n 'RampsService:getTokens',\n normalizedRegion,\n action,\n );\n },\n options,\n );\n\n this.update((state) => {\n const userRegion = state.userRegion?.toLowerCase().trim();\n\n if (userRegion === undefined || userRegion === normalizedRegion) {\n state.tokens = tokens;\n }\n });\n\n return tokens;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"RampsService-method-action-types.cjs","sourceRoot":"","sources":["../src/RampsService-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { RampsService } from './RampsService';\n\n/**\n * Makes a request to the API in order to retrieve the user's geolocation\n * based on their IP address.\n *\n * @returns The user's country/region code (e.g., \"US-UT\" for Utah, USA).\n */\nexport type RampsServiceGetGeolocationAction = {\n type: `RampsService:getGeolocation`;\n handler: RampsService['getGeolocation'];\n};\n\n/**\n * Makes a request to the cached API to retrieve the list of supported countries.\n * Filters countries based on aggregator support (preserves OnRampSDK logic).\n *\n * @param action - The ramp action type ('buy' or 'sell').\n * @returns An array of countries filtered by aggregator support.\n */\nexport type RampsServiceGetCountriesAction = {\n type: `RampsService:getCountries`;\n handler: RampsService['getCountries'];\n};\n\n/**\n * Fetches eligibility information for a specific region.\n *\n * @param isoCode - The ISO code for the region (e.g., \"us\", \"fr\", \"us-ny\").\n * @returns Eligibility information for the region.\n */\nexport type RampsServiceGetEligibilityAction = {\n type: `RampsService:getEligibility`;\n handler: RampsService['getEligibility'];\n};\n\n/**\n * Union of all RampsService action types.\n */\nexport type RampsServiceMethodActions =\n | RampsServiceGetGeolocationAction\n | RampsServiceGetCountriesAction\n | RampsServiceGetEligibilityAction;\n"]}
1
+ {"version":3,"file":"RampsService-method-action-types.cjs","sourceRoot":"","sources":["../src/RampsService-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { RampsService } from './RampsService';\n\n/**\n * Makes a request to the API in order to retrieve the user's geolocation\n * based on their IP address.\n *\n * @returns The user's country/region code (e.g., \"US-UT\" for Utah, USA).\n */\nexport type RampsServiceGetGeolocationAction = {\n type: `RampsService:getGeolocation`;\n handler: RampsService['getGeolocation'];\n};\n\n/**\n * Makes a request to the cached API to retrieve the list of supported countries.\n * Filters countries based on aggregator support (preserves OnRampSDK logic).\n *\n * @param action - The ramp action type ('buy' or 'sell').\n * @returns An array of countries filtered by aggregator support.\n */\nexport type RampsServiceGetCountriesAction = {\n type: `RampsService:getCountries`;\n handler: RampsService['getCountries'];\n};\n\n/**\n * Fetches eligibility information for a specific region.\n *\n * @param isoCode - The ISO code for the region (e.g., \"us\", \"fr\", \"us-ny\").\n * @returns Eligibility information for the region.\n */\nexport type RampsServiceGetEligibilityAction = {\n type: `RampsService:getEligibility`;\n handler: RampsService['getEligibility'];\n};\n\n/**\n * Fetches the list of available tokens for a given region and action.\n *\n * @param region - The region code (e.g., \"us\", \"fr\", \"us-ny\").\n * @param action - The ramp action type ('buy' or 'sell').\n * @returns The tokens response containing topTokens and allTokens.\n */\nexport type RampsServiceGetTokensAction = {\n type: `RampsService:getTokens`;\n handler: RampsService['getTokens'];\n};\n\n/**\n * Union of all RampsService action types.\n */\nexport type RampsServiceMethodActions =\n | RampsServiceGetGeolocationAction\n | RampsServiceGetCountriesAction\n | RampsServiceGetEligibilityAction\n | RampsServiceGetTokensAction;\n"]}
@@ -34,8 +34,19 @@ export type RampsServiceGetEligibilityAction = {
34
34
  type: `RampsService:getEligibility`;
35
35
  handler: RampsService['getEligibility'];
36
36
  };
37
+ /**
38
+ * Fetches the list of available tokens for a given region and action.
39
+ *
40
+ * @param region - The region code (e.g., "us", "fr", "us-ny").
41
+ * @param action - The ramp action type ('buy' or 'sell').
42
+ * @returns The tokens response containing topTokens and allTokens.
43
+ */
44
+ export type RampsServiceGetTokensAction = {
45
+ type: `RampsService:getTokens`;
46
+ handler: RampsService['getTokens'];
47
+ };
37
48
  /**
38
49
  * Union of all RampsService action types.
39
50
  */
40
- export type RampsServiceMethodActions = RampsServiceGetGeolocationAction | RampsServiceGetCountriesAction | RampsServiceGetEligibilityAction;
51
+ export type RampsServiceMethodActions = RampsServiceGetGeolocationAction | RampsServiceGetCountriesAction | RampsServiceGetEligibilityAction | RampsServiceGetTokensAction;
41
52
  //# sourceMappingURL=RampsService-method-action-types.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RampsService-method-action-types.d.cts","sourceRoot":"","sources":["../src/RampsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,2BAAuB;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;CACzC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C,IAAI,EAAE,2BAA2B,CAAC;IAClC,OAAO,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;CACvC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;CACzC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GACjC,gCAAgC,GAChC,8BAA8B,GAC9B,gCAAgC,CAAC"}
1
+ {"version":3,"file":"RampsService-method-action-types.d.cts","sourceRoot":"","sources":["../src/RampsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,2BAAuB;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;CACzC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C,IAAI,EAAE,2BAA2B,CAAC;IAClC,OAAO,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;CACvC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;CACzC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,wBAAwB,CAAC;IAC/B,OAAO,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GACjC,gCAAgC,GAChC,8BAA8B,GAC9B,gCAAgC,GAChC,2BAA2B,CAAC"}
@@ -34,8 +34,19 @@ export type RampsServiceGetEligibilityAction = {
34
34
  type: `RampsService:getEligibility`;
35
35
  handler: RampsService['getEligibility'];
36
36
  };
37
+ /**
38
+ * Fetches the list of available tokens for a given region and action.
39
+ *
40
+ * @param region - The region code (e.g., "us", "fr", "us-ny").
41
+ * @param action - The ramp action type ('buy' or 'sell').
42
+ * @returns The tokens response containing topTokens and allTokens.
43
+ */
44
+ export type RampsServiceGetTokensAction = {
45
+ type: `RampsService:getTokens`;
46
+ handler: RampsService['getTokens'];
47
+ };
37
48
  /**
38
49
  * Union of all RampsService action types.
39
50
  */
40
- export type RampsServiceMethodActions = RampsServiceGetGeolocationAction | RampsServiceGetCountriesAction | RampsServiceGetEligibilityAction;
51
+ export type RampsServiceMethodActions = RampsServiceGetGeolocationAction | RampsServiceGetCountriesAction | RampsServiceGetEligibilityAction | RampsServiceGetTokensAction;
41
52
  //# sourceMappingURL=RampsService-method-action-types.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RampsService-method-action-types.d.mts","sourceRoot":"","sources":["../src/RampsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,2BAAuB;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;CACzC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C,IAAI,EAAE,2BAA2B,CAAC;IAClC,OAAO,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;CACvC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;CACzC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GACjC,gCAAgC,GAChC,8BAA8B,GAC9B,gCAAgC,CAAC"}
1
+ {"version":3,"file":"RampsService-method-action-types.d.mts","sourceRoot":"","sources":["../src/RampsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,2BAAuB;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;CACzC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C,IAAI,EAAE,2BAA2B,CAAC;IAClC,OAAO,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;CACvC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;CACzC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,wBAAwB,CAAC;IAC/B,OAAO,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GACjC,gCAAgC,GAChC,8BAA8B,GAC9B,gCAAgC,GAChC,2BAA2B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"RampsService-method-action-types.mjs","sourceRoot":"","sources":["../src/RampsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { RampsService } from './RampsService';\n\n/**\n * Makes a request to the API in order to retrieve the user's geolocation\n * based on their IP address.\n *\n * @returns The user's country/region code (e.g., \"US-UT\" for Utah, USA).\n */\nexport type RampsServiceGetGeolocationAction = {\n type: `RampsService:getGeolocation`;\n handler: RampsService['getGeolocation'];\n};\n\n/**\n * Makes a request to the cached API to retrieve the list of supported countries.\n * Filters countries based on aggregator support (preserves OnRampSDK logic).\n *\n * @param action - The ramp action type ('buy' or 'sell').\n * @returns An array of countries filtered by aggregator support.\n */\nexport type RampsServiceGetCountriesAction = {\n type: `RampsService:getCountries`;\n handler: RampsService['getCountries'];\n};\n\n/**\n * Fetches eligibility information for a specific region.\n *\n * @param isoCode - The ISO code for the region (e.g., \"us\", \"fr\", \"us-ny\").\n * @returns Eligibility information for the region.\n */\nexport type RampsServiceGetEligibilityAction = {\n type: `RampsService:getEligibility`;\n handler: RampsService['getEligibility'];\n};\n\n/**\n * Union of all RampsService action types.\n */\nexport type RampsServiceMethodActions =\n | RampsServiceGetGeolocationAction\n | RampsServiceGetCountriesAction\n | RampsServiceGetEligibilityAction;\n"]}
1
+ {"version":3,"file":"RampsService-method-action-types.mjs","sourceRoot":"","sources":["../src/RampsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { RampsService } from './RampsService';\n\n/**\n * Makes a request to the API in order to retrieve the user's geolocation\n * based on their IP address.\n *\n * @returns The user's country/region code (e.g., \"US-UT\" for Utah, USA).\n */\nexport type RampsServiceGetGeolocationAction = {\n type: `RampsService:getGeolocation`;\n handler: RampsService['getGeolocation'];\n};\n\n/**\n * Makes a request to the cached API to retrieve the list of supported countries.\n * Filters countries based on aggregator support (preserves OnRampSDK logic).\n *\n * @param action - The ramp action type ('buy' or 'sell').\n * @returns An array of countries filtered by aggregator support.\n */\nexport type RampsServiceGetCountriesAction = {\n type: `RampsService:getCountries`;\n handler: RampsService['getCountries'];\n};\n\n/**\n * Fetches eligibility information for a specific region.\n *\n * @param isoCode - The ISO code for the region (e.g., \"us\", \"fr\", \"us-ny\").\n * @returns Eligibility information for the region.\n */\nexport type RampsServiceGetEligibilityAction = {\n type: `RampsService:getEligibility`;\n handler: RampsService['getEligibility'];\n};\n\n/**\n * Fetches the list of available tokens for a given region and action.\n *\n * @param region - The region code (e.g., \"us\", \"fr\", \"us-ny\").\n * @param action - The ramp action type ('buy' or 'sell').\n * @returns The tokens response containing topTokens and allTokens.\n */\nexport type RampsServiceGetTokensAction = {\n type: `RampsService:getTokens`;\n handler: RampsService['getTokens'];\n};\n\n/**\n * Union of all RampsService action types.\n */\nexport type RampsServiceMethodActions =\n | RampsServiceGetGeolocationAction\n | RampsServiceGetCountriesAction\n | RampsServiceGetEligibilityAction\n | RampsServiceGetTokensAction;\n"]}
@@ -51,6 +51,7 @@ const MESSENGER_EXPOSED_METHODS = [
51
51
  'getGeolocation',
52
52
  'getCountries',
53
53
  'getEligibility',
54
+ 'getTokens',
54
55
  ];
55
56
  // === SERVICE DEFINITION ===
56
57
  /**
@@ -251,6 +252,25 @@ class RampsService {
251
252
  const normalizedIsoCode = isoCode.toLowerCase().trim();
252
253
  return __classPrivateFieldGet(this, _RampsService_instances, "m", _RampsService_request).call(this, RampsApiService.Regions, `regions/countries/${normalizedIsoCode}`, { responseType: 'json' });
253
254
  }
255
+ /**
256
+ * Fetches the list of available tokens for a given region and action.
257
+ *
258
+ * @param region - The region code (e.g., "us", "fr", "us-ny").
259
+ * @param action - The ramp action type ('buy' or 'sell').
260
+ * @returns The tokens response containing topTokens and allTokens.
261
+ */
262
+ async getTokens(region, action = 'buy') {
263
+ const normalizedRegion = region.toLowerCase().trim();
264
+ const response = await __classPrivateFieldGet(this, _RampsService_instances, "m", _RampsService_request).call(this, RampsApiService.Regions, `regions/${normalizedRegion}/tokens`, { action, responseType: 'json' });
265
+ if (!response || typeof response !== 'object') {
266
+ throw new Error('Malformed response received from tokens API');
267
+ }
268
+ if (!Array.isArray(response.topTokens) ||
269
+ !Array.isArray(response.allTokens)) {
270
+ throw new Error('Malformed response received from tokens API');
271
+ }
272
+ return response;
273
+ }
254
274
  }
255
275
  exports.RampsService = RampsService;
256
276
  _a = RampsService, _RampsService_messenger = new WeakMap(), _RampsService_fetch = new WeakMap(), _RampsService_policy = new WeakMap(), _RampsService_environment = new WeakMap(), _RampsService_context = new WeakMap(), _RampsService_instances = new WeakSet(), _RampsService_addCommonParams = function _RampsService_addCommonParams(url, action) {
@@ -1 +1 @@
1
- {"version":3,"file":"RampsService.cjs","sourceRoot":"","sources":["../src/RampsService.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\n\nimport type { RampsServiceMethodActions } from './RampsService-method-action-types';\nimport packageJson from '../package.json';\n\n/**\n * Represents phone number information for a country.\n */\nexport type CountryPhone = {\n prefix: string;\n placeholder: string;\n template: string;\n};\n\n/**\n * Represents a state/province within a country.\n */\nexport type State = {\n /**\n * State identifier. Can be in path format (e.g., \"/regions/us-ut\") or ISO code format (e.g., \"us-ut\").\n */\n id?: string;\n /**\n * State name.\n */\n name?: string;\n /**\n * ISO state code (e.g., \"UT\", \"NY\").\n */\n stateId?: string;\n /**\n * Whether this state is supported for ramps.\n */\n supported?: boolean;\n /**\n * Whether this state is recommended.\n */\n recommended?: boolean;\n};\n\n/**\n * Represents eligibility information for a region.\n * Returned from the /regions/countries/{isoCode} endpoint.\n */\nexport type Eligibility = {\n /**\n * Whether aggregator providers are available.\n */\n aggregator?: boolean;\n /**\n * Whether deposit (buy) is available.\n */\n deposit?: boolean;\n /**\n * Whether global providers are available.\n */\n global?: boolean;\n};\n\n/**\n * Represents a country returned from the regions/countries API.\n */\nexport type Country = {\n /**\n * ISO-2 country code (e.g., \"US\", \"GB\").\n */\n isoCode: string;\n /**\n * Country identifier. Can be in path format (e.g., \"/regions/us\") or ISO code format.\n * If not provided, defaults to isoCode.\n */\n id?: string;\n /**\n * Country flag emoji or code.\n */\n flag: string;\n /**\n * Country name.\n */\n name: string;\n /**\n * Phone number information.\n */\n phone: CountryPhone;\n /**\n * Default currency code.\n */\n currency: string;\n /**\n * Whether this country is supported for ramps.\n */\n supported: boolean;\n /**\n * Whether this country is recommended.\n */\n recommended?: boolean;\n /**\n * Array of state objects.\n */\n states?: State[];\n};\n\n/**\n * The SDK version to send with API requests. (backwards-compatibility)\n */\nexport const RAMPS_SDK_VERSION = '2.1.6';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link RampsService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'RampsService';\n\n/**\n * The environment to use for API requests.\n */\nexport enum RampsEnvironment {\n Production = 'production',\n Staging = 'staging',\n Development = 'development',\n}\n\n/**\n * The type of ramps API service.\n * Determines which base URL to use (cache vs standard).\n */\nexport enum RampsApiService {\n Regions = 'regions',\n Orders = 'orders',\n}\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'getGeolocation',\n 'getCountries',\n 'getEligibility',\n] as const;\n\n/**\n * Actions that {@link RampsService} exposes to other consumers.\n */\nexport type RampsServiceActions = RampsServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link RampsService} calls.\n */\ntype AllowedActions = never;\n\n/**\n * Events that {@link RampsService} exposes to other consumers.\n */\nexport type RampsServiceEvents = never;\n\n/**\n * Events from other messengers that {@link RampsService} subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link RampsService}.\n */\nexport type RampsServiceMessenger = Messenger<\n typeof serviceName,\n RampsServiceActions | AllowedActions,\n RampsServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\n/**\n * Gets the base URL for API requests based on the environment and service type.\n * The Regions service uses a cache URL, while other services use the standard URL.\n *\n * @param environment - The environment to use.\n * @param service - The API service type (determines if cache URL is used).\n * @returns The base URL for API requests.\n */\nfunction getBaseUrl(\n environment: RampsEnvironment,\n service: RampsApiService,\n): string {\n const cache = service === RampsApiService.Regions ? '-cache' : '';\n\n switch (environment) {\n case RampsEnvironment.Production:\n return `https://on-ramp${cache}.api.cx.metamask.io`;\n case RampsEnvironment.Staging:\n case RampsEnvironment.Development:\n return `https://on-ramp${cache}.uat-api.cx.metamask.io`;\n default:\n throw new Error(`Invalid environment: ${String(environment)}`);\n }\n}\n\n/**\n * This service object is responsible for interacting with the Ramps API.\n *\n * @example\n *\n * ``` ts\n * import { Messenger } from '@metamask/messenger';\n * import type {\n * RampsServiceActions,\n * RampsServiceEvents,\n * } from '@metamask/ramps-controller';\n *\n * const rootMessenger = new Messenger<\n * 'Root',\n * RampsServiceActions\n * RampsServiceEvents\n * >({ namespace: 'Root' });\n * const rampsServiceMessenger = new Messenger<\n * 'RampsService',\n * RampsServiceActions,\n * RampsServiceEvents,\n * typeof rootMessenger,\n * >({\n * namespace: 'RampsService',\n * parent: rootMessenger,\n * });\n * // Instantiate the service to register its actions on the messenger\n * new RampsService({\n * messenger: rampsServiceMessenger,\n * environment: RampsEnvironment.Production,\n * context: 'mobile-ios',\n * fetch,\n * });\n *\n * // Later...\n * // Get the user's geolocation\n * const geolocation = await rootMessenger.call(\n * 'RampsService:getGeolocation',\n * );\n * // ... Do something with the geolocation ...\n * ```\n */\nexport class RampsService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ConstructorParameters<\n typeof RampsService\n >[0]['messenger'];\n\n /**\n * A function that can be used to make an HTTP request.\n */\n readonly #fetch: ConstructorParameters<typeof RampsService>[0]['fetch'];\n\n /**\n * The policy that wraps the request.\n *\n * @see {@link createServicePolicy}\n */\n readonly #policy: ServicePolicy;\n\n /**\n * The environment used for API requests.\n */\n readonly #environment: RampsEnvironment;\n\n /**\n * The context for API requests (e.g., 'mobile-ios', 'mobile-android').\n */\n readonly #context: string;\n\n /**\n * Constructs a new RampsService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.environment - The environment to use for API requests.\n * @param args.context - The context for API requests (e.g., 'mobile-ios', 'mobile-android').\n * @param args.fetch - A function that can be used to make an HTTP request. If\n * your JavaScript environment supports `fetch` natively, you'll probably want\n * to pass that; otherwise you can pass an equivalent (such as `fetch` via\n * `node-fetch`).\n * @param args.policyOptions - Options to pass to `createServicePolicy`, which\n * is used to wrap each request. See {@link CreateServicePolicyOptions}.\n */\n constructor({\n messenger,\n environment = RampsEnvironment.Staging,\n context,\n fetch: fetchFunction,\n policyOptions = {},\n }: {\n messenger: RampsServiceMessenger;\n environment?: RampsEnvironment;\n context: string;\n fetch: typeof fetch;\n policyOptions?: CreateServicePolicyOptions;\n }) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#fetch = fetchFunction;\n this.#policy = createServicePolicy(policyOptions);\n this.#environment = environment;\n this.#context = context;\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Registers a handler that will be called after a request returns a non-500\n * response, causing a retry. Primarily useful in tests where timers are being\n * mocked.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onRetry(\n listener: Parameters<ServicePolicy['onRetry']>[0],\n ): ReturnType<ServicePolicy['onRetry']> {\n return this.#policy.onRetry(listener);\n }\n\n /**\n * Registers a handler that will be called after a set number of retry rounds\n * prove that requests to the API endpoint consistently return a 5xx response.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onBreak(\n listener: Parameters<ServicePolicy['onBreak']>[0],\n ): ReturnType<ServicePolicy['onBreak']> {\n return this.#policy.onBreak(listener);\n }\n\n /**\n * Registers a handler that will be called under one of two circumstances:\n *\n * 1. After a set number of retries prove that requests to the API\n * consistently result in one of the following failures:\n * 1. A connection initiation error\n * 2. A connection reset error\n * 3. A timeout error\n * 4. A non-JSON response\n * 5. A 502, 503, or 504 response\n * 2. After a successful request is made to the API, but the response takes\n * longer than a set duration to return.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n */\n onDegraded(\n listener: Parameters<ServicePolicy['onDegraded']>[0],\n ): ReturnType<ServicePolicy['onDegraded']> {\n return this.#policy.onDegraded(listener);\n }\n\n /**\n * Adds common request parameters to a URL.\n *\n * @param url - The URL to add parameters to.\n * @param action - The ramp action type (optional, not all endpoints require it).\n */\n #addCommonParams(url: URL, action?: 'buy' | 'sell'): void {\n if (action) {\n url.searchParams.set('action', action);\n }\n url.searchParams.set('sdk', RAMPS_SDK_VERSION);\n url.searchParams.set('controller', packageJson.version);\n url.searchParams.set('context', this.#context);\n }\n\n /**\n * Makes an API request with retry policy and error handling.\n *\n * @param service - The API service type (determines base URL).\n * @param path - The endpoint path.\n * @param options - Request options.\n * @param options.action - The ramp action type (optional).\n * @param options.responseType - How to parse the response ('json' or 'text').\n * @returns The parsed response data.\n */\n async #request<TResponse>(\n service: RampsApiService,\n path: string,\n options: {\n action?: 'buy' | 'sell';\n responseType: 'json' | 'text';\n },\n ): Promise<TResponse> {\n return this.#policy.execute(async () => {\n const baseUrl = getBaseUrl(this.#environment, service);\n const url = new URL(path, baseUrl);\n this.#addCommonParams(url, options.action);\n\n const response = await this.#fetch(url);\n if (!response.ok) {\n throw new HttpError(\n response.status,\n `Fetching '${url.toString()}' failed with status '${response.status}'`,\n );\n }\n\n return options.responseType === 'json'\n ? (response.json() as Promise<TResponse>)\n : (response.text() as Promise<TResponse>);\n });\n }\n\n /**\n * Makes a request to the API in order to retrieve the user's geolocation\n * based on their IP address.\n *\n * @returns The user's country/region code (e.g., \"US-UT\" for Utah, USA).\n */\n async getGeolocation(): Promise<string> {\n const textResponse = await this.#request<string>(\n RampsApiService.Orders,\n 'geolocation',\n { responseType: 'text' },\n );\n\n const trimmedResponse = textResponse.trim();\n if (trimmedResponse.length > 0) {\n return trimmedResponse;\n }\n\n throw new Error('Malformed response received from geolocation API');\n }\n\n /**\n * Makes a request to the cached API to retrieve the list of supported countries.\n * Filters countries based on aggregator support (preserves OnRampSDK logic).\n *\n * @param action - The ramp action type ('buy' or 'sell').\n * @returns An array of countries filtered by aggregator support.\n */\n async getCountries(action: 'buy' | 'sell' = 'buy'): Promise<Country[]> {\n const countries = await this.#request<Country[]>(\n RampsApiService.Regions,\n 'regions/countries',\n { action, responseType: 'json' },\n );\n\n if (!Array.isArray(countries)) {\n throw new Error('Malformed response received from countries API');\n }\n\n return countries.filter((country) => {\n if (country.states && country.states.length > 0) {\n const hasSupportedState = country.states.some(\n (state) => state.supported !== false,\n );\n return country.supported || hasSupportedState;\n }\n\n return country.supported;\n });\n }\n\n /**\n * Fetches eligibility information for a specific region.\n *\n * @param isoCode - The ISO code for the region (e.g., \"us\", \"fr\", \"us-ny\").\n * @returns Eligibility information for the region.\n */\n async getEligibility(isoCode: string): Promise<Eligibility> {\n const normalizedIsoCode = isoCode.toLowerCase().trim();\n return this.#request<Eligibility>(\n RampsApiService.Regions,\n `regions/countries/${normalizedIsoCode}`,\n { responseType: 'json' },\n );\n }\n}\n"]}
1
+ {"version":3,"file":"RampsService.cjs","sourceRoot":"","sources":["../src/RampsService.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\n\nimport type { RampsServiceMethodActions } from './RampsService-method-action-types';\nimport packageJson from '../package.json';\n\n/**\n * Represents phone number information for a country.\n */\nexport type CountryPhone = {\n prefix: string;\n placeholder: string;\n template: string;\n};\n\n/**\n * Represents a state/province within a country.\n */\nexport type State = {\n /**\n * State identifier. Can be in path format (e.g., \"/regions/us-ut\") or ISO code format (e.g., \"us-ut\").\n */\n id?: string;\n /**\n * State name.\n */\n name?: string;\n /**\n * ISO state code (e.g., \"UT\", \"NY\").\n */\n stateId?: string;\n /**\n * Whether this state is supported for ramps.\n */\n supported?: boolean;\n /**\n * Whether this state is recommended.\n */\n recommended?: boolean;\n};\n\n/**\n * Represents eligibility information for a region.\n * Returned from the /regions/countries/{isoCode} endpoint.\n */\nexport type Eligibility = {\n /**\n * Whether aggregator providers are available.\n */\n aggregator?: boolean;\n /**\n * Whether deposit (buy) is available.\n */\n deposit?: boolean;\n /**\n * Whether global providers are available.\n */\n global?: boolean;\n};\n\n/**\n * Represents a country returned from the regions/countries API.\n */\nexport type Country = {\n /**\n * ISO-2 country code (e.g., \"US\", \"GB\").\n */\n isoCode: string;\n /**\n * Country identifier. Can be in path format (e.g., \"/regions/us\") or ISO code format.\n * If not provided, defaults to isoCode.\n */\n id?: string;\n /**\n * Country flag emoji or code.\n */\n flag: string;\n /**\n * Country name.\n */\n name: string;\n /**\n * Phone number information.\n */\n phone: CountryPhone;\n /**\n * Default currency code.\n */\n currency: string;\n /**\n * Whether this country is supported for ramps.\n */\n supported: boolean;\n /**\n * Whether this country is recommended.\n */\n recommended?: boolean;\n /**\n * Array of state objects.\n */\n states?: State[];\n};\n\n/**\n * Represents a token returned from the regions/{region}/tokens API.\n */\nexport type RampsToken = {\n /**\n * The asset identifier in CAIP-19 format (e.g., \"eip155:1/erc20:0x...\").\n */\n assetId: string;\n /**\n * The chain identifier in CAIP-2 format (e.g., \"eip155:1\").\n */\n chainId: string;\n /**\n * Token name (e.g., \"USD Coin\").\n */\n name: string;\n /**\n * Token symbol (e.g., \"USDC\").\n */\n symbol: string;\n /**\n * Number of decimals for the token.\n */\n decimals: number;\n /**\n * URL to the token icon.\n */\n iconUrl: string;\n /**\n * Whether this token is supported.\n */\n tokenSupported: boolean;\n};\n\n/**\n * Response from the regions/{region}/tokens API.\n */\nexport type TokensResponse = {\n /**\n * Top/popular tokens for the region.\n */\n topTokens: RampsToken[];\n /**\n * All available tokens for the region.\n */\n allTokens: RampsToken[];\n};\n\n/**\n * The SDK version to send with API requests. (backwards-compatibility)\n */\nexport const RAMPS_SDK_VERSION = '2.1.6';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link RampsService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'RampsService';\n\n/**\n * The environment to use for API requests.\n */\nexport enum RampsEnvironment {\n Production = 'production',\n Staging = 'staging',\n Development = 'development',\n}\n\n/**\n * The type of ramps API service.\n * Determines which base URL to use (cache vs standard).\n */\nexport enum RampsApiService {\n Regions = 'regions',\n Orders = 'orders',\n}\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'getGeolocation',\n 'getCountries',\n 'getEligibility',\n 'getTokens',\n] as const;\n\n/**\n * Actions that {@link RampsService} exposes to other consumers.\n */\nexport type RampsServiceActions = RampsServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link RampsService} calls.\n */\ntype AllowedActions = never;\n\n/**\n * Events that {@link RampsService} exposes to other consumers.\n */\nexport type RampsServiceEvents = never;\n\n/**\n * Events from other messengers that {@link RampsService} subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link RampsService}.\n */\nexport type RampsServiceMessenger = Messenger<\n typeof serviceName,\n RampsServiceActions | AllowedActions,\n RampsServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\n/**\n * Gets the base URL for API requests based on the environment and service type.\n * The Regions service uses a cache URL, while other services use the standard URL.\n *\n * @param environment - The environment to use.\n * @param service - The API service type (determines if cache URL is used).\n * @returns The base URL for API requests.\n */\nfunction getBaseUrl(\n environment: RampsEnvironment,\n service: RampsApiService,\n): string {\n const cache = service === RampsApiService.Regions ? '-cache' : '';\n\n switch (environment) {\n case RampsEnvironment.Production:\n return `https://on-ramp${cache}.api.cx.metamask.io`;\n case RampsEnvironment.Staging:\n case RampsEnvironment.Development:\n return `https://on-ramp${cache}.uat-api.cx.metamask.io`;\n default:\n throw new Error(`Invalid environment: ${String(environment)}`);\n }\n}\n\n/**\n * This service object is responsible for interacting with the Ramps API.\n *\n * @example\n *\n * ``` ts\n * import { Messenger } from '@metamask/messenger';\n * import type {\n * RampsServiceActions,\n * RampsServiceEvents,\n * } from '@metamask/ramps-controller';\n *\n * const rootMessenger = new Messenger<\n * 'Root',\n * RampsServiceActions\n * RampsServiceEvents\n * >({ namespace: 'Root' });\n * const rampsServiceMessenger = new Messenger<\n * 'RampsService',\n * RampsServiceActions,\n * RampsServiceEvents,\n * typeof rootMessenger,\n * >({\n * namespace: 'RampsService',\n * parent: rootMessenger,\n * });\n * // Instantiate the service to register its actions on the messenger\n * new RampsService({\n * messenger: rampsServiceMessenger,\n * environment: RampsEnvironment.Production,\n * context: 'mobile-ios',\n * fetch,\n * });\n *\n * // Later...\n * // Get the user's geolocation\n * const geolocation = await rootMessenger.call(\n * 'RampsService:getGeolocation',\n * );\n * // ... Do something with the geolocation ...\n * ```\n */\nexport class RampsService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ConstructorParameters<\n typeof RampsService\n >[0]['messenger'];\n\n /**\n * A function that can be used to make an HTTP request.\n */\n readonly #fetch: ConstructorParameters<typeof RampsService>[0]['fetch'];\n\n /**\n * The policy that wraps the request.\n *\n * @see {@link createServicePolicy}\n */\n readonly #policy: ServicePolicy;\n\n /**\n * The environment used for API requests.\n */\n readonly #environment: RampsEnvironment;\n\n /**\n * The context for API requests (e.g., 'mobile-ios', 'mobile-android').\n */\n readonly #context: string;\n\n /**\n * Constructs a new RampsService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.environment - The environment to use for API requests.\n * @param args.context - The context for API requests (e.g., 'mobile-ios', 'mobile-android').\n * @param args.fetch - A function that can be used to make an HTTP request. If\n * your JavaScript environment supports `fetch` natively, you'll probably want\n * to pass that; otherwise you can pass an equivalent (such as `fetch` via\n * `node-fetch`).\n * @param args.policyOptions - Options to pass to `createServicePolicy`, which\n * is used to wrap each request. See {@link CreateServicePolicyOptions}.\n */\n constructor({\n messenger,\n environment = RampsEnvironment.Staging,\n context,\n fetch: fetchFunction,\n policyOptions = {},\n }: {\n messenger: RampsServiceMessenger;\n environment?: RampsEnvironment;\n context: string;\n fetch: typeof fetch;\n policyOptions?: CreateServicePolicyOptions;\n }) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#fetch = fetchFunction;\n this.#policy = createServicePolicy(policyOptions);\n this.#environment = environment;\n this.#context = context;\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Registers a handler that will be called after a request returns a non-500\n * response, causing a retry. Primarily useful in tests where timers are being\n * mocked.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onRetry(\n listener: Parameters<ServicePolicy['onRetry']>[0],\n ): ReturnType<ServicePolicy['onRetry']> {\n return this.#policy.onRetry(listener);\n }\n\n /**\n * Registers a handler that will be called after a set number of retry rounds\n * prove that requests to the API endpoint consistently return a 5xx response.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onBreak(\n listener: Parameters<ServicePolicy['onBreak']>[0],\n ): ReturnType<ServicePolicy['onBreak']> {\n return this.#policy.onBreak(listener);\n }\n\n /**\n * Registers a handler that will be called under one of two circumstances:\n *\n * 1. After a set number of retries prove that requests to the API\n * consistently result in one of the following failures:\n * 1. A connection initiation error\n * 2. A connection reset error\n * 3. A timeout error\n * 4. A non-JSON response\n * 5. A 502, 503, or 504 response\n * 2. After a successful request is made to the API, but the response takes\n * longer than a set duration to return.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n */\n onDegraded(\n listener: Parameters<ServicePolicy['onDegraded']>[0],\n ): ReturnType<ServicePolicy['onDegraded']> {\n return this.#policy.onDegraded(listener);\n }\n\n /**\n * Adds common request parameters to a URL.\n *\n * @param url - The URL to add parameters to.\n * @param action - The ramp action type (optional, not all endpoints require it).\n */\n #addCommonParams(url: URL, action?: 'buy' | 'sell'): void {\n if (action) {\n url.searchParams.set('action', action);\n }\n url.searchParams.set('sdk', RAMPS_SDK_VERSION);\n url.searchParams.set('controller', packageJson.version);\n url.searchParams.set('context', this.#context);\n }\n\n /**\n * Makes an API request with retry policy and error handling.\n *\n * @param service - The API service type (determines base URL).\n * @param path - The endpoint path.\n * @param options - Request options.\n * @param options.action - The ramp action type (optional).\n * @param options.responseType - How to parse the response ('json' or 'text').\n * @returns The parsed response data.\n */\n async #request<TResponse>(\n service: RampsApiService,\n path: string,\n options: {\n action?: 'buy' | 'sell';\n responseType: 'json' | 'text';\n },\n ): Promise<TResponse> {\n return this.#policy.execute(async () => {\n const baseUrl = getBaseUrl(this.#environment, service);\n const url = new URL(path, baseUrl);\n this.#addCommonParams(url, options.action);\n\n const response = await this.#fetch(url);\n if (!response.ok) {\n throw new HttpError(\n response.status,\n `Fetching '${url.toString()}' failed with status '${response.status}'`,\n );\n }\n\n return options.responseType === 'json'\n ? (response.json() as Promise<TResponse>)\n : (response.text() as Promise<TResponse>);\n });\n }\n\n /**\n * Makes a request to the API in order to retrieve the user's geolocation\n * based on their IP address.\n *\n * @returns The user's country/region code (e.g., \"US-UT\" for Utah, USA).\n */\n async getGeolocation(): Promise<string> {\n const textResponse = await this.#request<string>(\n RampsApiService.Orders,\n 'geolocation',\n { responseType: 'text' },\n );\n\n const trimmedResponse = textResponse.trim();\n if (trimmedResponse.length > 0) {\n return trimmedResponse;\n }\n\n throw new Error('Malformed response received from geolocation API');\n }\n\n /**\n * Makes a request to the cached API to retrieve the list of supported countries.\n * Filters countries based on aggregator support (preserves OnRampSDK logic).\n *\n * @param action - The ramp action type ('buy' or 'sell').\n * @returns An array of countries filtered by aggregator support.\n */\n async getCountries(action: 'buy' | 'sell' = 'buy'): Promise<Country[]> {\n const countries = await this.#request<Country[]>(\n RampsApiService.Regions,\n 'regions/countries',\n { action, responseType: 'json' },\n );\n\n if (!Array.isArray(countries)) {\n throw new Error('Malformed response received from countries API');\n }\n\n return countries.filter((country) => {\n if (country.states && country.states.length > 0) {\n const hasSupportedState = country.states.some(\n (state) => state.supported !== false,\n );\n return country.supported || hasSupportedState;\n }\n\n return country.supported;\n });\n }\n\n /**\n * Fetches eligibility information for a specific region.\n *\n * @param isoCode - The ISO code for the region (e.g., \"us\", \"fr\", \"us-ny\").\n * @returns Eligibility information for the region.\n */\n async getEligibility(isoCode: string): Promise<Eligibility> {\n const normalizedIsoCode = isoCode.toLowerCase().trim();\n return this.#request<Eligibility>(\n RampsApiService.Regions,\n `regions/countries/${normalizedIsoCode}`,\n { responseType: 'json' },\n );\n }\n\n /**\n * Fetches the list of available tokens for a given region and action.\n *\n * @param region - The region code (e.g., \"us\", \"fr\", \"us-ny\").\n * @param action - The ramp action type ('buy' or 'sell').\n * @returns The tokens response containing topTokens and allTokens.\n */\n async getTokens(\n region: string,\n action: 'buy' | 'sell' = 'buy',\n ): Promise<TokensResponse> {\n const normalizedRegion = region.toLowerCase().trim();\n const response = await this.#request<TokensResponse>(\n RampsApiService.Regions,\n `regions/${normalizedRegion}/tokens`,\n { action, responseType: 'json' },\n );\n\n if (!response || typeof response !== 'object') {\n throw new Error('Malformed response received from tokens API');\n }\n\n if (\n !Array.isArray(response.topTokens) ||\n !Array.isArray(response.allTokens)\n ) {\n throw new Error('Malformed response received from tokens API');\n }\n\n return response;\n }\n}\n"]}
@@ -94,6 +94,52 @@ export type Country = {
94
94
  */
95
95
  states?: State[];
96
96
  };
97
+ /**
98
+ * Represents a token returned from the regions/{region}/tokens API.
99
+ */
100
+ export type RampsToken = {
101
+ /**
102
+ * The asset identifier in CAIP-19 format (e.g., "eip155:1/erc20:0x...").
103
+ */
104
+ assetId: string;
105
+ /**
106
+ * The chain identifier in CAIP-2 format (e.g., "eip155:1").
107
+ */
108
+ chainId: string;
109
+ /**
110
+ * Token name (e.g., "USD Coin").
111
+ */
112
+ name: string;
113
+ /**
114
+ * Token symbol (e.g., "USDC").
115
+ */
116
+ symbol: string;
117
+ /**
118
+ * Number of decimals for the token.
119
+ */
120
+ decimals: number;
121
+ /**
122
+ * URL to the token icon.
123
+ */
124
+ iconUrl: string;
125
+ /**
126
+ * Whether this token is supported.
127
+ */
128
+ tokenSupported: boolean;
129
+ };
130
+ /**
131
+ * Response from the regions/{region}/tokens API.
132
+ */
133
+ export type TokensResponse = {
134
+ /**
135
+ * Top/popular tokens for the region.
136
+ */
137
+ topTokens: RampsToken[];
138
+ /**
139
+ * All available tokens for the region.
140
+ */
141
+ allTokens: RampsToken[];
142
+ };
97
143
  /**
98
144
  * The SDK version to send with API requests. (backwards-compatibility)
99
145
  */
@@ -270,6 +316,14 @@ export declare class RampsService {
270
316
  * @returns Eligibility information for the region.
271
317
  */
272
318
  getEligibility(isoCode: string): Promise<Eligibility>;
319
+ /**
320
+ * Fetches the list of available tokens for a given region and action.
321
+ *
322
+ * @param region - The region code (e.g., "us", "fr", "us-ny").
323
+ * @param action - The ramp action type ('buy' or 'sell').
324
+ * @returns The tokens response containing topTokens and allTokens.
325
+ */
326
+ getTokens(region: string, action?: 'buy' | 'sell'): Promise<TokensResponse>;
273
327
  }
274
328
  export {};
275
329
  //# sourceMappingURL=RampsService.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RampsService.d.cts","sourceRoot":"","sources":["../src/RampsService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RampsService.d.cts","sourceRoot":"","sources":["../src/RampsService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAC1B,aAAa,EACd,mCAAmC;AAEpC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EAAE,yBAAyB,EAAE,+CAA2C;AAGpF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG;IAClB;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,YAAY,CAAC;IACpB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB;;OAEG;IACH,SAAS,EAAE,UAAU,EAAE,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,UAAU,CAAC;AAIzC;;;GAGG;AACH,eAAO,MAAM,WAAW,iBAAiB,CAAC;AAE1C;;GAEG;AACH,oBAAY,gBAAgB;IAC1B,UAAU,eAAe;IACzB,OAAO,YAAY;IACnB,WAAW,gBAAgB;CAC5B;AAED;;;GAGG;AACH,oBAAY,eAAe;IACzB,OAAO,YAAY;IACnB,MAAM,WAAW;CAClB;AAWD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,yBAAyB,CAAC;AAE5D;;GAEG;AACH,KAAK,cAAc,GAAG,KAAK,CAAC;AAE5B;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAEvC;;GAEG;AACH,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,SAAS,CAC3C,OAAO,WAAW,EAClB,mBAAmB,GAAG,cAAc,EACpC,kBAAkB,GAAG,aAAa,CACnC,CAAC;AA6BF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,qBAAa,YAAY;;IACvB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,WAAW,CAAC;IA+BlC;;;;;;;;;;;;;OAaG;gBACS,EACV,SAAS,EACT,WAAsC,EACtC,OAAO,EACP,KAAK,EAAE,aAAa,EACpB,aAAkB,GACnB,EAAE;QACD,SAAS,EAAE,qBAAqB,CAAC;QACjC,WAAW,CAAC,EAAE,gBAAgB,CAAC;QAC/B,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,OAAO,KAAK,CAAC;QACpB,aAAa,CAAC,EAAE,0BAA0B,CAAC;KAC5C;IAcD;;;;;;;;;OASG;IACH,OAAO,CACL,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAChD,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAIvC;;;;;;;;OAQG;IACH,OAAO,CACL,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAChD,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAIvC;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,CACR,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,GACnD,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAwD1C;;;;;OAKG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAevC;;;;;;OAMG;IACG,YAAY,CAAC,MAAM,GAAE,KAAK,GAAG,MAAc,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAuBtE;;;;;OAKG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAS3D;;;;;;OAMG;IACG,SAAS,CACb,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,KAAK,GAAG,MAAc,GAC7B,OAAO,CAAC,cAAc,CAAC;CAqB3B"}