diff --git a/packages/ramps-controller/CHANGELOG.md b/packages/ramps-controller/CHANGELOG.md index b2106f101b6..9474427484d 100644 --- a/packages/ramps-controller/CHANGELOG.md +++ b/packages/ramps-controller/CHANGELOG.md @@ -7,6 +7,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Expose all public `RampsController` methods through its messenger ([#8221](https://github.com/MetaMask/core/pull/8221)) + - The following actions are now available: + - `RampsController:executeRequest` + - `RampsController:abortRequest` + - `RampsController:getRequestState` + - `RampsController:setUserRegion` + - `RampsController:setSelectedProvider` + - `RampsController:init` + - `RampsController:getCountries` + - `RampsController:getTokens` + - `RampsController:getProviders` + - `RampsController:getPaymentMethods` + - `RampsController:setSelectedPaymentMethod` + - `RampsController:addOrder` + - `RampsController:removeOrder` + - `RampsController:startOrderPolling` + - `RampsController:stopOrderPolling` + - `RampsController:getBuyWidgetData` + - `RampsController:addPrecreatedOrder` + - `RampsController:getOrderFromCallback` + - `RampsController:transakSetApiKey` + - `RampsController:transakSetAccessToken` + - `RampsController:transakClearAccessToken` + - `RampsController:transakSetAuthenticated` + - `RampsController:transakResetState` + - `RampsController:transakSendUserOtp` + - `RampsController:transakVerifyUserOtp` + - `RampsController:transakLogout` + - `RampsController:transakGetUserDetails` + - `RampsController:transakGetBuyQuote` + - `RampsController:transakGetKycRequirement` + - `RampsController:transakGetAdditionalRequirements` + - `RampsController:transakCreateOrder` + - `RampsController:transakGetOrder` + - `RampsController:transakGetUserLimits` + - `RampsController:transakRequestOtt` + - `RampsController:transakGeneratePaymentWidgetUrl` + - `RampsController:transakSubmitPurposeOfUsageForm` + - `RampsController:transakPatchUser` + - `RampsController:transakSubmitSsnDetails` + - `RampsController:transakConfirmPayment` + - `RampsController:transakGetTranslation` + - `RampsController:transakGetIdProofStatus` + - `RampsController:transakCancelOrder` + - `RampsController:transakCancelAllActiveOrders` + - `RampsController:transakGetActiveOrders` + - Corresponding action types are now exported (e.g. `RampsControllerGetOrderAction`) + ## [12.0.0] ### Changed diff --git a/packages/ramps-controller/src/RampsController-method-action-types.ts b/packages/ramps-controller/src/RampsController-method-action-types.ts new file mode 100644 index 00000000000..e1bccd50175 --- /dev/null +++ b/packages/ramps-controller/src/RampsController-method-action-types.ts @@ -0,0 +1,657 @@ +/** + * This file is auto generated by `scripts/generate-method-action-types.ts`. + * Do not edit manually. + */ + +import type { RampsController } from './RampsController'; + +/** + * Executes a request with caching, deduplication, and at most one in-flight + * request per resource type. + * + * 1. **Same cache key in flight** – If a request with this cache key is + * already pending, returns that promise (deduplication; no second request). + * + * 2. **Cache hit** – If valid, non-expired data exists in state.requests for + * this key and forceRefresh is not set, returns that data without fetching. + * + * 3. **New request** – Creates an AbortController and fires the fetcher. + * If options.resourceType is set, tags the pending request with that + * resource type (so #abortDependentRequests can cancel it on region + * change or cleanup) and ref-counts resource-level loading state. + * On success or error, updates request state and resource error; + * in finally, clears resource loading only if this request was not + * aborted. + * + * @param cacheKey - Unique identifier for this request (e.g. from createCacheKey). + * @param fetcher - Async function that performs the fetch. Receives an AbortSignal + * that is aborted when this request is superseded by another for the same resource. + * @param options - Optional forceRefresh, ttl, and resourceType for loading/error state. + * @returns The result of the request (from cache, joined promise, or fetcher). + */ +export type RampsControllerExecuteRequestAction = { + type: `RampsController:executeRequest`; + handler: RampsController['executeRequest']; +}; + +/** + * Aborts a pending request if one exists. + * + * @param cacheKey - The cache key of the request to abort. + * @returns True if a request was aborted. + */ +export type RampsControllerAbortRequestAction = { + type: `RampsController:abortRequest`; + handler: RampsController['abortRequest']; +}; + +/** + * Gets the state of a specific cached request. + * + * @param cacheKey - The cache key to look up. + * @returns The request state, or undefined if not cached. + */ +export type RampsControllerGetRequestStateAction = { + type: `RampsController:getRequestState`; + handler: RampsController['getRequestState']; +}; + +/** + * Sets the user's region manually (without fetching geolocation). + * This allows users to override the detected region. + * + * @param region - The region code to set (e.g., "US-CA"). + * @param options - Options for cache behavior. + * @returns The user region object. + */ +export type RampsControllerSetUserRegionAction = { + type: `RampsController:setUserRegion`; + handler: RampsController['setUserRegion']; +}; + +/** + * Sets the user's selected provider by ID, or clears the selection. + * Looks up the provider from the current providers in state and automatically + * fetches payment methods for that provider. + * + * @param providerId - The provider ID (e.g., "/providers/moonpay"), or null to clear. + * @throws If region is not set, providers are not loaded, or provider is not found. + */ +export type RampsControllerSetSelectedProviderAction = { + type: `RampsController:setSelectedProvider`; + handler: RampsController['setSelectedProvider']; +}; + +/** + * 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. + * + * Idempotent: subsequent calls return the same promise unless forceRefresh is set. + * Skips getCountries when countries are already loaded; skips geolocation when + * userRegion already exists. + * + * @param options - Options for cache behavior. forceRefresh bypasses idempotency and re-runs the full flow. + * @returns Promise that resolves when initialization is complete. + */ +export type RampsControllerInitAction = { + type: `RampsController:init`; + handler: RampsController['init']; +}; + +/** + * Fetches the list of supported countries. + * The API returns countries with support information for both buy and sell actions. + * The countries are saved in the controller state once fetched. + * + * @param options - Options for cache behavior. + * @returns An array of countries. + */ +export type RampsControllerGetCountriesAction = { + type: `RampsController:getCountries`; + handler: RampsController['getCountries']; +}; + +/** + * Fetches the list of available tokens for a given region and action. + * The tokens are saved in the controller state once fetched. + * + * @param region - The region code (e.g., "us", "fr", "us-ny"). If not provided, uses the user's region from controller state. + * @param action - The ramp action type ('buy' or 'sell'). + * @param options - Options for cache behavior and query filters. + * @param options.provider - Provider ID(s) to filter by. + * @returns The tokens response containing topTokens and allTokens. + */ +export type RampsControllerGetTokensAction = { + type: `RampsController:getTokens`; + handler: RampsController['getTokens']; +}; + +/** + * Sets the user's selected token by asset ID. + * Looks up the token from the current tokens in state and automatically + * fetches payment methods for that token. + * + * @param assetId - The asset identifier in CAIP-19 format (e.g., "eip155:1/erc20:0x..."), or undefined to clear. + * @throws If region is not set, tokens are not loaded, or token is not found. + */ +export type RampsControllerSetSelectedTokenAction = { + type: `RampsController:setSelectedToken`; + handler: RampsController['setSelectedToken']; +}; + +/** + * Fetches the list of providers for a given region. + * The providers are saved in the controller state once fetched. + * + * @param region - The region code (e.g., "us", "fr", "us-ny"). If not provided, uses the user's region from controller state. + * @param options - Options for cache behavior and query filters. + * @param options.provider - Provider ID(s) to filter by. + * @param options.crypto - Crypto currency ID(s) to filter by. + * @param options.fiat - Fiat currency ID(s) to filter by. + * @param options.payments - Payment method ID(s) to filter by. + * @returns The providers response containing providers array. + */ +export type RampsControllerGetProvidersAction = { + type: `RampsController:getProviders`; + handler: RampsController['getProviders']; +}; + +/** + * Fetches the list of payment methods for a given context. + * The payment methods are saved in the controller state once fetched. + * + * @param region - User's region code (e.g. "fr", "us-ny"). + * @param options - Query parameters for filtering payment methods. + * @param options.fiat - Fiat currency code (e.g., "usd"). If not provided, uses the user's region currency. + * @param options.assetId - CAIP-19 cryptocurrency identifier. + * @param options.provider - Provider ID path. + * @returns The payment methods response containing payments array. + */ +export type RampsControllerGetPaymentMethodsAction = { + type: `RampsController:getPaymentMethods`; + handler: RampsController['getPaymentMethods']; +}; + +/** + * Sets the user's selected payment method by ID. + * Looks up the payment method from the current payment methods in state. + * + * @param paymentMethodId - The payment method ID (e.g., "/payments/debit-credit-card"), or null to clear. + * @throws If payment methods are not loaded or payment method is not found. + */ +export type RampsControllerSetSelectedPaymentMethodAction = { + type: `RampsController:setSelectedPaymentMethod`; + handler: RampsController['setSelectedPaymentMethod']; +}; + +/** + * Fetches quotes from all providers for a given set of parameters. + * Uses the controller's request cache; callers manage the response in local state. + * + * @param options - The parameters for fetching quotes. + * @param options.region - User's region code. If not provided, uses userRegion from state. + * @param options.fiat - Fiat currency code. If not provided, uses userRegion currency. + * @param options.assetId - CAIP-19 cryptocurrency identifier. + * @param options.amount - The amount (in fiat for buy, crypto for sell). + * @param options.walletAddress - The destination wallet address. + * @param options.paymentMethods - Array of payment method IDs. If not provided, uses paymentMethods from state. + * @param options.providers - Optional provider IDs to filter quotes. + * @param options.redirectUrl - Optional redirect URL after order completion. + * @param options.action - The ramp action type. Defaults to 'buy'. + * @param options.forceRefresh - Whether to bypass cache. + * @param options.ttl - Custom TTL for this request. + * @returns The quotes response containing success, sorted, error, and customActions. + */ +export type RampsControllerGetQuotesAction = { + type: `RampsController:getQuotes`; + handler: RampsController['getQuotes']; +}; + +/** + * Adds or updates a V2 order in controller state. + * If an order with the same providerOrderId already exists, the incoming + * fields are merged on top of the existing order so that fields not present + * in the update (e.g. paymentDetails from the Transak API) are preserved. + * + * @param order - The RampsOrder to add or update. + */ +export type RampsControllerAddOrderAction = { + type: `RampsController:addOrder`; + handler: RampsController['addOrder']; +}; + +/** + * Removes a V2 order from controller state by providerOrderId. + * + * @param providerOrderId - The provider order ID to remove. + */ +export type RampsControllerRemoveOrderAction = { + type: `RampsController:removeOrder`; + handler: RampsController['removeOrder']; +}; + +/** + * Starts polling all pending V2 orders at a fixed interval. + * Each poll cycle iterates orders with non-terminal statuses, + * respects pollingSecondsMinimum and backoff from error count. + */ +export type RampsControllerStartOrderPollingAction = { + type: `RampsController:startOrderPolling`; + handler: RampsController['startOrderPolling']; +}; + +/** + * Stops order polling and clears the interval. + */ +export type RampsControllerStopOrderPollingAction = { + type: `RampsController:stopOrderPolling`; + handler: RampsController['stopOrderPolling']; +}; + +/** + * Fetches the widget data from a quote for redirect providers. + * Makes a request to the buyURL endpoint via the RampsService to get the + * actual provider widget URL and optional order ID for polling. + * + * @param quote - The quote to fetch the widget URL from. + * @returns Promise resolving to the full BuyWidget (url, browser, orderId), or null if not available (missing buyURL or empty url in response). + * @throws Rethrows errors from the RampsService (e.g. HttpError, network failures) so clients can react to fetch failures. + */ +export type RampsControllerGetBuyWidgetDataAction = { + type: `RampsController:getBuyWidgetData`; + handler: RampsController['getBuyWidgetData']; +}; + +/** + * Registers an order ID for polling until the order is created or resolved. + * Adds a minimal stub order to controller state; the existing order polling + * will fetch the full order when the provider has created it. + * + * @param params - Object containing order identifiers and wallet info. + * @param params.orderId - Full order ID (e.g. "/providers/paypal/orders/abc123") or order code. + * @param params.providerCode - Provider code (e.g. "paypal", "transak"), with or without /providers/ prefix. + * @param params.walletAddress - Wallet address for the order. + * @param params.chainId - Optional chain ID for the order. + */ +export type RampsControllerAddPrecreatedOrderAction = { + type: `RampsController:addPrecreatedOrder`; + handler: RampsController['addPrecreatedOrder']; +}; + +/** + * Fetches an order from the unified V2 API endpoint. + * Returns a normalized RampsOrder for all provider types (aggregator and native). + * + * @param providerCode - The provider code (e.g., "transak", "transak-native", "moonpay"). + * @param orderCode - The order identifier. + * @param wallet - The wallet address associated with the order. + * @returns The unified order data. + */ +export type RampsControllerGetOrderAction = { + type: `RampsController:getOrder`; + handler: RampsController['getOrder']; +}; + +/** + * Extracts an order from a provider callback URL. + * Sends the callback URL to the V2 backend for provider-specific parsing, + * then fetches the full order. This is the V2 equivalent of the aggregator + * SDK's `getOrderFromCallback`. + * + * @param providerCode - The provider code (e.g., "transak", "moonpay"). + * @param callbackUrl - The full callback URL the provider redirected to. + * @param wallet - The wallet address associated with the order. + * @returns The unified order data. + */ +export type RampsControllerGetOrderFromCallbackAction = { + type: `RampsController:getOrderFromCallback`; + handler: RampsController['getOrderFromCallback']; +}; + +/** + * Sets the Transak API key used for all Transak API requests. + * + * @param apiKey - The Transak API key. + */ +export type RampsControllerTransakSetApiKeyAction = { + type: `RampsController:transakSetApiKey`; + handler: RampsController['transakSetApiKey']; +}; + +/** + * Sets the Transak access token and marks the user as authenticated. + * + * @param token - The access token received from Transak auth. + */ +export type RampsControllerTransakSetAccessTokenAction = { + type: `RampsController:transakSetAccessToken`; + handler: RampsController['transakSetAccessToken']; +}; + +/** + * Clears the Transak access token and marks the user as unauthenticated. + */ +export type RampsControllerTransakClearAccessTokenAction = { + type: `RampsController:transakClearAccessToken`; + handler: RampsController['transakClearAccessToken']; +}; + +/** + * Updates the Transak authentication flag in controller state. + * + * @param isAuthenticated - Whether the user is authenticated with Transak. + */ +export type RampsControllerTransakSetAuthenticatedAction = { + type: `RampsController:transakSetAuthenticated`; + handler: RampsController['transakSetAuthenticated']; +}; + +/** + * Resets all Transak state back to defaults (unauthenticated, no data). + */ +export type RampsControllerTransakResetStateAction = { + type: `RampsController:transakResetState`; + handler: RampsController['transakResetState']; +}; + +/** + * Sends a one-time password to the user's email for Transak authentication. + * + * @param email - The user's email address. + * @returns The OTP response containing a state token for verification. + */ +export type RampsControllerTransakSendUserOtpAction = { + type: `RampsController:transakSendUserOtp`; + handler: RampsController['transakSendUserOtp']; +}; + +/** + * Verifies a one-time password and authenticates the user with Transak. + * Updates the controller's authentication state on success. + * + * @param email - The user's email address. + * @param verificationCode - The OTP code entered by the user. + * @param stateToken - The state token from the sendUserOtp response. + * @returns The access token for subsequent authenticated requests. + */ +export type RampsControllerTransakVerifyUserOtpAction = { + type: `RampsController:transakVerifyUserOtp`; + handler: RampsController['transakVerifyUserOtp']; +}; + +/** + * Logs the user out of Transak. Clears authentication state and user details + * regardless of whether the API call succeeds or fails. + * + * @returns A message indicating the logout result. + */ +export type RampsControllerTransakLogoutAction = { + type: `RampsController:transakLogout`; + handler: RampsController['transakLogout']; +}; + +/** + * Fetches the authenticated user's details from Transak. + * Updates the userDetails resource state with loading/success/error states. + * + * @returns The user's profile and KYC details. + */ +export type RampsControllerTransakGetUserDetailsAction = { + type: `RampsController:transakGetUserDetails`; + handler: RampsController['transakGetUserDetails']; +}; + +/** + * Fetches a buy quote from Transak for the given parameters. + * Updates the buyQuote resource state with loading/success/error states. + * + * @param fiatCurrency - The fiat currency code (e.g., "USD"). + * @param cryptoCurrency - The cryptocurrency identifier. + * @param network - The blockchain network identifier. + * @param paymentMethod - The payment method identifier. + * @param fiatAmount - The fiat amount as a string. + * @returns The buy quote with pricing and fee details. + */ +export type RampsControllerTransakGetBuyQuoteAction = { + type: `RampsController:transakGetBuyQuote`; + handler: RampsController['transakGetBuyQuote']; +}; + +/** + * Fetches the KYC requirement for a given quote. + * Updates the kycRequirement resource state with loading/success/error states. + * + * @param quoteId - The quote ID to check KYC requirements for. + * @returns The KYC requirement status and whether the user can place an order. + */ +export type RampsControllerTransakGetKycRequirementAction = { + type: `RampsController:transakGetKycRequirement`; + handler: RampsController['transakGetKycRequirement']; +}; + +/** + * Fetches additional KYC requirements (e.g., ID proof, address proof) for a quote. + * + * @param quoteId - The quote ID to check additional requirements for. + * @returns The list of additional forms required. + */ +export type RampsControllerTransakGetAdditionalRequirementsAction = { + type: `RampsController:transakGetAdditionalRequirements`; + handler: RampsController['transakGetAdditionalRequirements']; +}; + +/** + * Creates a new order on Transak. If an existing order conflicts (HTTP 409), + * active orders are cancelled and the creation is retried. + * + * @param quoteId - The quote ID to create an order from. + * @param walletAddress - The destination wallet address. + * @param paymentMethodId - The payment method to use. + * @returns The created deposit order. + */ +export type RampsControllerTransakCreateOrderAction = { + type: `RampsController:transakCreateOrder`; + handler: RampsController['transakCreateOrder']; +}; + +/** + * Fetches an existing order from Transak by order ID. + * + * @param orderId - The order ID (deposit format or raw Transak format). + * @param wallet - The wallet address associated with the order. + * @param paymentDetails - Optional payment details to attach to the order. + * @returns The deposit order details. + */ +export type RampsControllerTransakGetOrderAction = { + type: `RampsController:transakGetOrder`; + handler: RampsController['transakGetOrder']; +}; + +/** + * Fetches the user's spending limits for a given currency and payment method. + * + * @param fiatCurrency - The fiat currency code. + * @param paymentMethod - The payment method identifier. + * @param kycType - The KYC level type. + * @returns The user's limits, spending, and remaining amounts. + */ +export type RampsControllerTransakGetUserLimitsAction = { + type: `RampsController:transakGetUserLimits`; + handler: RampsController['transakGetUserLimits']; +}; + +/** + * Requests a one-time token (OTT) for the Transak payment widget. + * + * @returns The OTT response containing the token. + */ +export type RampsControllerTransakRequestOttAction = { + type: `RampsController:transakRequestOtt`; + handler: RampsController['transakRequestOtt']; +}; + +/** + * Generates a URL for the Transak payment widget with pre-filled parameters. + * + * @param ottToken - The one-time token for widget authentication. + * @param quote - The buy quote to pre-fill in the widget. + * @param walletAddress - The destination wallet address. + * @param extraParams - Optional additional URL parameters. + * @returns The fully constructed widget URL string. + */ +export type RampsControllerTransakGeneratePaymentWidgetUrlAction = { + type: `RampsController:transakGeneratePaymentWidgetUrl`; + handler: RampsController['transakGeneratePaymentWidgetUrl']; +}; + +/** + * Submits the user's purpose of usage form for KYC compliance. + * + * @param purpose - Array of purpose strings selected by the user. + * @returns A promise that resolves when the form is submitted. + */ +export type RampsControllerTransakSubmitPurposeOfUsageFormAction = { + type: `RampsController:transakSubmitPurposeOfUsageForm`; + handler: RampsController['transakSubmitPurposeOfUsageForm']; +}; + +/** + * Updates the user's personal or address details on Transak. + * + * @param data - The user data fields to update. + * @returns The API response data. + */ +export type RampsControllerTransakPatchUserAction = { + type: `RampsController:transakPatchUser`; + handler: RampsController['transakPatchUser']; +}; + +/** + * Submits the user's SSN for identity verification. + * + * @param ssn - The Social Security Number. + * @param quoteId - The quote ID associated with the order requiring SSN. + * @returns The API response data. + */ +export type RampsControllerTransakSubmitSsnDetailsAction = { + type: `RampsController:transakSubmitSsnDetails`; + handler: RampsController['transakSubmitSsnDetails']; +}; + +/** + * Confirms payment for an order after the user has completed payment. + * + * @param orderId - The order ID to confirm payment for. + * @param paymentMethodId - The payment method used. + * @returns Whether the payment confirmation was successful. + */ +export type RampsControllerTransakConfirmPaymentAction = { + type: `RampsController:transakConfirmPayment`; + handler: RampsController['transakConfirmPayment']; +}; + +/** + * Translates generic ramps identifiers to Transak-specific identifiers. + * + * @param request - The translation request with optional identifiers to translate. + * @returns The translated Transak-specific identifiers. + */ +export type RampsControllerTransakGetTranslationAction = { + type: `RampsController:transakGetTranslation`; + handler: RampsController['transakGetTranslation']; +}; + +/** + * Checks the status of an ID proof submission for KYC. + * + * @param workFlowRunId - The workflow run ID to check status for. + * @returns The current ID proof status. + */ +export type RampsControllerTransakGetIdProofStatusAction = { + type: `RampsController:transakGetIdProofStatus`; + handler: RampsController['transakGetIdProofStatus']; +}; + +/** + * Cancels a specific Transak order. + * + * @param depositOrderId - The deposit order ID to cancel. + * @returns A promise that resolves when the order is cancelled. + */ +export type RampsControllerTransakCancelOrderAction = { + type: `RampsController:transakCancelOrder`; + handler: RampsController['transakCancelOrder']; +}; + +/** + * Cancels all active Transak orders. Individual cancellation failures + * are collected and returned rather than thrown. + * + * @returns An array of errors from any failed cancellations (empty if all succeeded). + */ +export type RampsControllerTransakCancelAllActiveOrdersAction = { + type: `RampsController:transakCancelAllActiveOrders`; + handler: RampsController['transakCancelAllActiveOrders']; +}; + +/** + * Fetches all active Transak orders for the authenticated user. + * + * @returns The list of active orders. + */ +export type RampsControllerTransakGetActiveOrdersAction = { + type: `RampsController:transakGetActiveOrders`; + handler: RampsController['transakGetActiveOrders']; +}; + +/** + * Union of all RampsController action types. + */ +export type RampsControllerMethodActions = + | RampsControllerExecuteRequestAction + | RampsControllerAbortRequestAction + | RampsControllerGetRequestStateAction + | RampsControllerSetUserRegionAction + | RampsControllerSetSelectedProviderAction + | RampsControllerInitAction + | RampsControllerGetCountriesAction + | RampsControllerGetTokensAction + | RampsControllerSetSelectedTokenAction + | RampsControllerGetProvidersAction + | RampsControllerGetPaymentMethodsAction + | RampsControllerSetSelectedPaymentMethodAction + | RampsControllerGetQuotesAction + | RampsControllerAddOrderAction + | RampsControllerRemoveOrderAction + | RampsControllerStartOrderPollingAction + | RampsControllerStopOrderPollingAction + | RampsControllerGetBuyWidgetDataAction + | RampsControllerAddPrecreatedOrderAction + | RampsControllerGetOrderAction + | RampsControllerGetOrderFromCallbackAction + | RampsControllerTransakSetApiKeyAction + | RampsControllerTransakSetAccessTokenAction + | RampsControllerTransakClearAccessTokenAction + | RampsControllerTransakSetAuthenticatedAction + | RampsControllerTransakResetStateAction + | RampsControllerTransakSendUserOtpAction + | RampsControllerTransakVerifyUserOtpAction + | RampsControllerTransakLogoutAction + | RampsControllerTransakGetUserDetailsAction + | RampsControllerTransakGetBuyQuoteAction + | RampsControllerTransakGetKycRequirementAction + | RampsControllerTransakGetAdditionalRequirementsAction + | RampsControllerTransakCreateOrderAction + | RampsControllerTransakGetOrderAction + | RampsControllerTransakGetUserLimitsAction + | RampsControllerTransakRequestOttAction + | RampsControllerTransakGeneratePaymentWidgetUrlAction + | RampsControllerTransakSubmitPurposeOfUsageFormAction + | RampsControllerTransakPatchUserAction + | RampsControllerTransakSubmitSsnDetailsAction + | RampsControllerTransakConfirmPaymentAction + | RampsControllerTransakGetTranslationAction + | RampsControllerTransakGetIdProofStatusAction + | RampsControllerTransakCancelOrderAction + | RampsControllerTransakCancelAllActiveOrdersAction + | RampsControllerTransakGetActiveOrdersAction; diff --git a/packages/ramps-controller/src/RampsController.test.ts b/packages/ramps-controller/src/RampsController.test.ts index daa7965089b..35b59ca268f 100644 --- a/packages/ramps-controller/src/RampsController.test.ts +++ b/packages/ramps-controller/src/RampsController.test.ts @@ -444,7 +444,10 @@ describe('RampsController', () => { expect(controller.state.providers.data).toStrictEqual([]); - const result = await controller.getProviders('us-ca'); + const result = await rootMessenger.call( + 'RampsController:getProviders', + 'us-ca', + ); expect(result.providers).toStrictEqual(mockProviders); expect(controller.state.providers.data).toStrictEqual(mockProviders); @@ -452,7 +455,7 @@ describe('RampsController', () => { }); it('caches responses for the same region', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let callCount = 0; rootMessenger.registerActionHandler( 'RampsService:getProviders', @@ -462,15 +465,15 @@ describe('RampsController', () => { }, ); - await controller.getProviders('us-ca'); - await controller.getProviders('us-ca'); + await rootMessenger.call('RampsController:getProviders', 'us-ca'); + await rootMessenger.call('RampsController:getProviders', 'us-ca'); expect(callCount).toBe(1); }); }); it('normalizes region case and caches with normalized key', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let callCount = 0; rootMessenger.registerActionHandler( 'RampsService:getProviders', @@ -481,15 +484,15 @@ describe('RampsController', () => { }, ); - await controller.getProviders('US-ca'); - await controller.getProviders('us-ca'); + await rootMessenger.call('RampsController:getProviders', 'US-ca'); + await rootMessenger.call('RampsController:getProviders', 'us-ca'); expect(callCount).toBe(1); }); }); it('creates separate cache entries for different regions', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let callCount = 0; rootMessenger.registerActionHandler( 'RampsService:getProviders', @@ -499,8 +502,8 @@ describe('RampsController', () => { }, ); - await controller.getProviders('us-ca'); - await controller.getProviders('fr'); + await rootMessenger.call('RampsController:getProviders', 'us-ca'); + await rootMessenger.call('RampsController:getProviders', 'fr'); expect(callCount).toBe(2); }); @@ -515,7 +518,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let receivedRegion: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getProviders', @@ -525,7 +528,7 @@ describe('RampsController', () => { }, ); - await controller.getProviders(); + await rootMessenger.call('RampsController:getProviders'); expect(receivedRegion).toBe('fr'); }, @@ -541,7 +544,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let receivedRegion: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getProviders', @@ -551,7 +554,7 @@ describe('RampsController', () => { }, ); - await controller.getProviders('us-ca'); + await rootMessenger.call('RampsController:getProviders', 'us-ca'); expect(receivedRegion).toBe('us-ca'); }, @@ -579,7 +582,7 @@ describe('RampsController', () => { expect(controller.state.userRegion?.regionCode).toBe('us-ca'); expect(controller.state.providers.data).toStrictEqual([]); - await controller.getProviders('US-ca'); + await rootMessenger.call('RampsController:getProviders', 'US-ca'); expect(controller.state.providers.data).toStrictEqual(mockProviders); }, @@ -627,7 +630,7 @@ describe('RampsController', () => { existingProviders, ); - await controller.getProviders('fr'); + await rootMessenger.call('RampsController:getProviders', 'fr'); expect(controller.state.providers.data).toStrictEqual( existingProviders, @@ -637,7 +640,7 @@ describe('RampsController', () => { }); it('passes filter options to the service', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let receivedOptions: | { provider?: string | string[]; @@ -662,7 +665,7 @@ describe('RampsController', () => { }, ); - await controller.getProviders('us-ca', { + await rootMessenger.call('RampsController:getProviders', 'us-ca', { provider: 'paypal', crypto: 'ETH', fiat: 'USD', @@ -679,8 +682,10 @@ describe('RampsController', () => { }); it('throws error when region is not provided and userRegion is not set', async () => { - await withController(async ({ controller }) => { - await expect(controller.getProviders()).rejects.toThrow( + await withController(async ({ rootMessenger }) => { + await expect( + rootMessenger.call('RampsController:getProviders'), + ).rejects.toThrow( 'Region is required. Cannot proceed without valid region information.', ); }); @@ -696,7 +701,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let serviceCalled = false; rootMessenger.registerActionHandler( 'RampsService:getProviders', @@ -706,7 +711,10 @@ describe('RampsController', () => { }, ); - const result = await controller.getProviders('us-ca'); + const result = await rootMessenger.call( + 'RampsController:getProviders', + 'us-ca', + ); expect(serviceCalled).toBe(true); expect(result.providers).toStrictEqual(mockProviders); @@ -724,7 +732,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let serviceCalled = false; rootMessenger.registerActionHandler( 'RampsService:getProviders', @@ -734,7 +742,9 @@ describe('RampsController', () => { }, ); - await controller.getProviders('us-ca', { provider: 'moonpay' }); + await rootMessenger.call('RampsController:getProviders', 'us-ca', { + provider: 'moonpay', + }); expect(serviceCalled).toBe(true); }, @@ -952,17 +962,22 @@ describe('RampsController', () => { describe('executeRequest', () => { it('returns cached data when available and not expired', async () => { - await withController(async ({ controller }) => { + await withController(async ({ rootMessenger }) => { let callCount = 0; const fetcher = async (): Promise => { callCount += 1; return 'cached-result'; }; - await controller.executeRequest('cache-test-key', fetcher); + await rootMessenger.call( + 'RampsController:executeRequest', + 'cache-test-key', + fetcher, + ); expect(callCount).toBe(1); - const result = await controller.executeRequest( + const result = await rootMessenger.call( + 'RampsController:executeRequest', 'cache-test-key', fetcher, ); @@ -972,7 +987,7 @@ describe('RampsController', () => { }); it('deduplicates concurrent requests with the same cache key', async () => { - await withController(async ({ controller }) => { + await withController(async ({ rootMessenger }) => { let callCount = 0; const fetcher = async (): Promise => { callCount += 1; @@ -981,8 +996,16 @@ describe('RampsController', () => { }; const [result1, result2] = await Promise.all([ - controller.executeRequest('test-key', fetcher), - controller.executeRequest('test-key', fetcher), + rootMessenger.call( + 'RampsController:executeRequest', + 'test-key', + fetcher, + ), + rootMessenger.call( + 'RampsController:executeRequest', + 'test-key', + fetcher, + ), ]); expect(callCount).toBe(1); @@ -992,13 +1015,17 @@ describe('RampsController', () => { }); it('stores error state when request fails', async () => { - await withController(async ({ controller }) => { + await withController(async ({ controller, rootMessenger }) => { const fetcher = async (): Promise => { throw new Error('Test error'); }; await expect( - controller.executeRequest('error-key', fetcher), + rootMessenger.call( + 'RampsController:executeRequest', + 'error-key', + fetcher, + ), ).rejects.toThrow('Test error'); const requestState = controller.state.requests['error-key']; @@ -1008,7 +1035,7 @@ describe('RampsController', () => { }); it('stores fallback error message when error has no message', async () => { - await withController(async ({ controller }) => { + await withController(async ({ controller, rootMessenger }) => { const fetcher = async (): Promise => { const error = new Error(); Object.defineProperty(error, 'message', { value: undefined }); @@ -1016,7 +1043,11 @@ describe('RampsController', () => { }; await expect( - controller.executeRequest('error-key-no-message', fetcher), + rootMessenger.call( + 'RampsController:executeRequest', + 'error-key-no-message', + fetcher, + ), ).rejects.toThrow(Error); const requestState = controller.state.requests['error-key-no-message']; @@ -1026,7 +1057,7 @@ describe('RampsController', () => { }); it('sets loading state while request is in progress', async () => { - await withController(async ({ controller }) => { + await withController(async ({ controller, rootMessenger }) => { let resolvePromise: (value: string) => void; const fetcher = async (): Promise => { return new Promise((resolve) => { @@ -1034,7 +1065,8 @@ describe('RampsController', () => { }); }; - const requestPromise = controller.executeRequest( + const requestPromise = rootMessenger.call( + 'RampsController:executeRequest', 'loading-key', fetcher, ); @@ -1054,7 +1086,7 @@ describe('RampsController', () => { }); it('keeps resource isLoading true until last concurrent request (different cache keys) finishes', async () => { - await withController(async ({ controller }) => { + await withController(async ({ controller, rootMessenger }) => { let resolveFirst: (value: string) => void; let resolveSecond: (value: string) => void; const fetcherA = async (): Promise => { @@ -1068,12 +1100,14 @@ describe('RampsController', () => { }); }; - const promiseA = controller.executeRequest( + const promiseA = rootMessenger.call( + 'RampsController:executeRequest', 'providers-key-a', fetcherA, { resourceType: 'providers' }, ); - const promiseB = controller.executeRequest( + const promiseB = rootMessenger.call( + 'RampsController:executeRequest', 'providers-key-b', fetcherB, { resourceType: 'providers' }, @@ -1096,7 +1130,7 @@ describe('RampsController', () => { }); it('clears resource loading when ref-count hits zero even if map was cleared (defensive)', async () => { - await withController(async ({ controller }) => { + await withController(async ({ controller, rootMessenger }) => { let resolveFetcher: (value: string) => void; const fetcher = async (): Promise => { return new Promise((resolve) => { @@ -1104,7 +1138,8 @@ describe('RampsController', () => { }); }; - const promise = controller.executeRequest( + const promise = rootMessenger.call( + 'RampsController:executeRequest', 'providers-defensive-key', fetcher, { resourceType: 'providers' }, @@ -1125,7 +1160,7 @@ describe('RampsController', () => { describe('abortRequest', () => { it('aborts a pending request', async () => { - await withController(async ({ controller }) => { + await withController(async ({ rootMessenger }) => { let wasAborted = false; const fetcher = async (signal: AbortSignal): Promise => { return new Promise((_resolve, reject) => { @@ -1136,8 +1171,15 @@ describe('RampsController', () => { }); }; - const requestPromise = controller.executeRequest('abort-key', fetcher); - const didAbort = controller.abortRequest('abort-key'); + const requestPromise = rootMessenger.call( + 'RampsController:executeRequest', + 'abort-key', + fetcher, + ); + const didAbort = rootMessenger.call( + 'RampsController:abortRequest', + 'abort-key', + ); expect(didAbort).toBe(true); await expect(requestPromise).rejects.toThrow('Aborted'); @@ -1146,14 +1188,17 @@ describe('RampsController', () => { }); it('returns false if no pending request exists', async () => { - await withController(({ controller }) => { - const didAbort = controller.abortRequest('non-existent-key'); + await withController(({ rootMessenger }) => { + const didAbort = rootMessenger.call( + 'RampsController:abortRequest', + 'non-existent-key', + ); expect(didAbort).toBe(false); }); }); it('clears LOADING state from requests cache when aborted', async () => { - await withController(async ({ controller }) => { + await withController(async ({ controller, rootMessenger }) => { const fetcher = async (signal: AbortSignal): Promise => { return new Promise((_resolve, reject) => { signal.addEventListener('abort', () => { @@ -1162,13 +1207,17 @@ describe('RampsController', () => { }); }; - const requestPromise = controller.executeRequest('abort-key', fetcher); + const requestPromise = rootMessenger.call( + 'RampsController:executeRequest', + 'abort-key', + fetcher, + ); expect(controller.state.requests['abort-key']?.status).toBe( RequestStatus.LOADING, ); - controller.abortRequest('abort-key'); + rootMessenger.call('RampsController:abortRequest', 'abort-key'); expect(controller.state.requests['abort-key']).toBeUndefined(); @@ -1177,7 +1226,7 @@ describe('RampsController', () => { }); it('throws if fetch completes after abort signal is triggered', async () => { - await withController(async ({ controller }) => { + await withController(async ({ rootMessenger }) => { const fetcher = async (signal: AbortSignal): Promise => { // Simulate: abort is called, but fetcher still returns successfully signal.dispatchEvent(new Event('abort')); @@ -1185,7 +1234,8 @@ describe('RampsController', () => { return 'completed-after-abort'; }; - const requestPromise = controller.executeRequest( + const requestPromise = rootMessenger.call( + 'RampsController:executeRequest', 'abort-after-success-key', fetcher, ); @@ -1195,7 +1245,7 @@ describe('RampsController', () => { }); it('does not delete newer pending request when aborted request settles', async () => { - await withController(async ({ controller }) => { + await withController(async ({ rootMessenger }) => { let requestASettled = false; let requestBCallCount = 0; @@ -1220,17 +1270,29 @@ describe('RampsController', () => { }; // Start request A - const promiseA = controller.executeRequest('race-key', fetcherA); + const promiseA = rootMessenger.call( + 'RampsController:executeRequest', + 'race-key', + fetcherA, + ); // Abort request A (removes from pendingRequests, triggers abort) - controller.abortRequest('race-key'); + rootMessenger.call('RampsController:abortRequest', 'race-key'); // Start request B with the same key before request A settles expect(requestASettled).toBe(false); - const promiseB = controller.executeRequest('race-key', fetcherB); + const promiseB = rootMessenger.call( + 'RampsController:executeRequest', + 'race-key', + fetcherB, + ); // Start request C with same key - should deduplicate with B - const promiseC = controller.executeRequest('race-key', fetcherB); + const promiseC = rootMessenger.call( + 'RampsController:executeRequest', + 'race-key', + fetcherB, + ); // Wait for request A to finish settling (its finally block runs) await expect(promiseA).rejects.toThrow('Request A aborted'); @@ -1250,14 +1312,30 @@ describe('RampsController', () => { it('evicts oldest entries when cache exceeds max size', async () => { await withController( { options: { requestCacheMaxSize: 3 } }, - async ({ controller }) => { - await controller.executeRequest('key1', async () => 'data1'); + async ({ controller, rootMessenger }) => { + await rootMessenger.call( + 'RampsController:executeRequest', + 'key1', + async () => 'data1', + ); await new Promise((resolve) => setTimeout(resolve, 20)); - await controller.executeRequest('key2', async () => 'data2'); + await rootMessenger.call( + 'RampsController:executeRequest', + 'key2', + async () => 'data2', + ); await new Promise((resolve) => setTimeout(resolve, 20)); - await controller.executeRequest('key3', async () => 'data3'); + await rootMessenger.call( + 'RampsController:executeRequest', + 'key3', + async () => 'data3', + ); await new Promise((resolve) => setTimeout(resolve, 20)); - await controller.executeRequest('key4', async () => 'data4'); + await rootMessenger.call( + 'RampsController:executeRequest', + 'key4', + async () => 'data4', + ); const keys = Object.keys(controller.state.requests); expect(keys).toHaveLength(3); @@ -1272,7 +1350,7 @@ describe('RampsController', () => { it('handles entries with missing timestamps during eviction', async () => { await withController( { options: { requestCacheMaxSize: 2 } }, - async ({ controller }) => { + async ({ controller, rootMessenger }) => { // Manually inject cache entries with missing timestamps // This shouldn't happen in normal usage but tests the defensive fallback // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -1297,7 +1375,11 @@ describe('RampsController', () => { }); // Adding a fourth entry should trigger eviction of 2 entries - await controller.executeRequest('key4', async () => 'data4'); + await rootMessenger.call( + 'RampsController:executeRequest', + 'key4', + async () => 'data4', + ); const keys = Object.keys(controller.state.requests); expect(keys).toHaveLength(2); @@ -1314,9 +1396,17 @@ describe('RampsController', () => { const shortTTL = 100; await withController( { options: { requestCacheTTL: shortTTL, requestCacheMaxSize: 100 } }, - async ({ controller }) => { - await controller.executeRequest('key1', async () => 'data1'); - await controller.executeRequest('key2', async () => 'data2'); + async ({ controller, rootMessenger }) => { + await rootMessenger.call( + 'RampsController:executeRequest', + 'key1', + async () => 'data1', + ); + await rootMessenger.call( + 'RampsController:executeRequest', + 'key2', + async () => 'data2', + ); const keysBeforeExpiry = Object.keys(controller.state.requests); expect(keysBeforeExpiry).toContain('key1'); @@ -1324,7 +1414,11 @@ describe('RampsController', () => { await new Promise((resolve) => setTimeout(resolve, shortTTL + 50)); - await controller.executeRequest('key3', async () => 'data3'); + await rootMessenger.call( + 'RampsController:executeRequest', + 'key3', + async () => 'data3', + ); const keysAfterExpiry = Object.keys(controller.state.requests); expect(keysAfterExpiry).not.toContain('key1'); @@ -1338,13 +1432,25 @@ describe('RampsController', () => { const longTTL = 1000; await withController( { options: { requestCacheTTL: longTTL, requestCacheMaxSize: 100 } }, - async ({ controller }) => { - await controller.executeRequest('key1', async () => 'data1'); - await controller.executeRequest('key2', async () => 'data2'); + async ({ controller, rootMessenger }) => { + await rootMessenger.call( + 'RampsController:executeRequest', + 'key1', + async () => 'data1', + ); + await rootMessenger.call( + 'RampsController:executeRequest', + 'key2', + async () => 'data2', + ); await new Promise((resolve) => setTimeout(resolve, 50)); - await controller.executeRequest('key3', async () => 'data3'); + await rootMessenger.call( + 'RampsController:executeRequest', + 'key3', + async () => 'data3', + ); const keys = Object.keys(controller.state.requests); expect(keys).toContain('key1'); @@ -1357,18 +1463,28 @@ describe('RampsController', () => { describe('getRequestState', () => { it('returns the cached request state', async () => { - await withController(async ({ controller }) => { - await controller.executeRequest('state-key', async () => 'data'); + await withController(async ({ rootMessenger }) => { + await rootMessenger.call( + 'RampsController:executeRequest', + 'state-key', + async () => 'data', + ); - const state = controller.getRequestState('state-key'); + const state = rootMessenger.call( + 'RampsController:getRequestState', + 'state-key', + ); expect(state?.status).toBe(RequestStatus.SUCCESS); expect(state?.data).toBe('data'); }); }); it('returns undefined for non-existent cache key', async () => { - await withController(({ controller }) => { - const state = controller.getRequestState('non-existent'); + await withController(({ rootMessenger }) => { + const state = rootMessenger.call( + 'RampsController:getRequestState', + 'non-existent', + ); expect(state).toBeUndefined(); }); }); @@ -1412,7 +1528,9 @@ describe('RampsController', () => { expect(controller.state.countries.data).toStrictEqual([]); - const countries = await controller.getCountries(); + const countries = await rootMessenger.call( + 'RampsController:getCountries', + ); expect(countries).toMatchInlineSnapshot(` [ @@ -1460,7 +1578,9 @@ describe('RampsController', () => { async () => 'not an array' as unknown as Country[], ); - const countries = await controller.getCountries(); + const countries = await rootMessenger.call( + 'RampsController:getCountries', + ); expect(countries).toBe('not an array'); expect(controller.state.countries.data).toStrictEqual([]); @@ -1479,14 +1599,14 @@ describe('RampsController', () => { state: stateWithNullCountries, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getCountries', async () => mockCountries, ); - await expect(controller.getCountries()).rejects.toThrow( - /Cannot set propert(y|ies) of null/u, - ); + await expect( + rootMessenger.call('RampsController:getCountries'), + ).rejects.toThrow(/Cannot set propert(y|ies) of null/u); }, ); }); @@ -1504,7 +1624,7 @@ describe('RampsController', () => { async () => createMockCountries(), ); - await controller.init(); + await rootMessenger.call('RampsController:init'); expect(controller.state.countries.data).toStrictEqual( createMockCountries(), @@ -1529,7 +1649,7 @@ describe('RampsController', () => { async () => createMockCountries(), ); - await controller.init(); + await rootMessenger.call('RampsController:init'); expect(controller.state.countries.data).toStrictEqual( createMockCountries(), @@ -1603,7 +1723,7 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await controller.init(); + await rootMessenger.call('RampsController:init'); // Verify persisted state is preserved expect(controller.state.userRegion?.regionCode).toBe('us-ca'); @@ -1617,7 +1737,7 @@ describe('RampsController', () => { }); it('throws error when geolocation fetch fails', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getCountries', async () => createMockCountries(), @@ -1627,14 +1747,16 @@ describe('RampsController', () => { async () => null as unknown as string, ); - await expect(controller.init()).rejects.toThrow( + await expect( + rootMessenger.call('RampsController:init'), + ).rejects.toThrow( 'Failed to fetch geolocation. Cannot initialize controller without valid region information.', ); }); }); it('handles countries fetch failure', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getCountries', async () => { @@ -1642,14 +1764,14 @@ describe('RampsController', () => { }, ); - await expect(controller.init()).rejects.toThrow( - 'Countries fetch error', - ); + await expect( + rootMessenger.call('RampsController:init'), + ).rejects.toThrow('Countries fetch error'); }); }); it('rejects when init fails with error that has no message', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const errorWithoutMessage = Object.assign(new Error(), { code: 'ERR_NO_MESSAGE', message: undefined, @@ -1662,14 +1784,16 @@ describe('RampsController', () => { }, ); - await expect(controller.init()).rejects.toMatchObject({ + await expect( + rootMessenger.call('RampsController:init'), + ).rejects.toMatchObject({ code: 'ERR_NO_MESSAGE', }); }); }); it('does not double-fetch when init() called twice concurrently', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let getCountriesCallCount = 0; rootMessenger.registerActionHandler( 'RampsService:getGeolocation', @@ -1691,13 +1815,16 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await Promise.all([controller.init(), controller.init()]); + await Promise.all([ + rootMessenger.call('RampsController:init'), + rootMessenger.call('RampsController:init'), + ]); expect(getCountriesCallCount).toBe(1); }); }); it('returns immediately on second init() after first completes', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let getCountriesCallCount = 0; rootMessenger.registerActionHandler( 'RampsService:getGeolocation', @@ -1719,8 +1846,8 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await controller.init(); - await controller.init(); + await rootMessenger.call('RampsController:init'); + await rootMessenger.call('RampsController:init'); expect(getCountriesCallCount).toBe(1); }); }); @@ -1761,7 +1888,7 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await controller.init(); + await rootMessenger.call('RampsController:init'); expect(getCountriesCalled).toBe(false); expect(getGeolocationCalled).toBe(false); @@ -1772,7 +1899,7 @@ describe('RampsController', () => { it('forceRefresh bypasses idempotency and re-runs full flow', async () => { let getCountriesCallCount = 0; - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getGeolocation', async () => 'us-ca', @@ -1793,10 +1920,12 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await controller.init(); + await rootMessenger.call('RampsController:init'); expect(getCountriesCallCount).toBe(1); - await controller.init({ forceRefresh: true }); + await rootMessenger.call('RampsController:init', { + forceRefresh: true, + }); expect(getCountriesCallCount).toBe(2); }); }); @@ -1822,7 +1951,7 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await controller.setUserRegion('US-CA'); + await rootMessenger.call('RampsController:setUserRegion', 'US-CA'); expect(controller.state.userRegion?.regionCode).toBe('us-ca'); expect(controller.state.userRegion?.country.isoCode).toBe('US'); @@ -1884,10 +2013,16 @@ describe('RampsController', () => { async () => ({ payments: [mockPaymentMethod] }), ); - await controller.setUserRegion('US-ca'); + await rootMessenger.call('RampsController:setUserRegion', 'US-ca'); await new Promise((resolve) => setTimeout(resolve, 50)); - await controller.getPaymentMethods('us-ca'); - controller.setSelectedPaymentMethod(mockPaymentMethod.id); + await rootMessenger.call( + 'RampsController:getPaymentMethods', + 'us-ca', + ); + rootMessenger.call( + 'RampsController:setSelectedPaymentMethod', + mockPaymentMethod.id, + ); expect(controller.state.tokens.data).toStrictEqual(mockTokens); expect(controller.state.providers.data).toStrictEqual(mockProviders); @@ -1899,7 +2034,7 @@ describe('RampsController', () => { ); providersToReturn = []; - await controller.setUserRegion('FR'); + await rootMessenger.call('RampsController:setUserRegion', 'FR'); await new Promise((resolve) => setTimeout(resolve, 50)); expect(controller.state.tokens.data).toStrictEqual(mockTokens); expect(controller.state.providers.data).toStrictEqual([]); @@ -1934,8 +2069,8 @@ describe('RampsController', () => { async () => providersPromise, ); - await controller.setUserRegion('US-ca'); - await controller.setUserRegion('FR'); + await rootMessenger.call('RampsController:setUserRegion', 'US-ca'); + await rootMessenger.call('RampsController:setUserRegion', 'FR'); await new Promise((resolve) => setTimeout(resolve, 50)); expect(controller.state.userRegion?.regionCode).toBe('fr'); @@ -2005,7 +2140,7 @@ describe('RampsController', () => { ); // Set the same region - await controller.setUserRegion('US-ca'); + await rootMessenger.call('RampsController:setUserRegion', 'US-ca'); // Verify persisted state is preserved expect(controller.state.userRegion?.regionCode).toBe('us-ca'); @@ -2088,7 +2223,7 @@ describe('RampsController', () => { ); // Set a different region - await controller.setUserRegion('FR'); + await rootMessenger.call('RampsController:setUserRegion', 'FR'); // Verify persisted state is cleared expect(controller.state.userRegion?.regionCode).toBe('fr'); @@ -2138,7 +2273,7 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await controller.setUserRegion('us-ca'); + await rootMessenger.call('RampsController:setUserRegion', 'us-ca'); expect(controller.state.userRegion?.regionCode).toBe('us-ca'); expect(controller.state.userRegion?.country.name).toBe( @@ -2179,7 +2314,7 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await controller.setUserRegion('fr'); + await rootMessenger.call('RampsController:setUserRegion', 'fr'); expect(controller.state.userRegion?.regionCode).toBe('fr'); expect(controller.state.userRegion?.country.name).toBe('France'); @@ -2225,7 +2360,7 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await controller.setUserRegion('us-ca'); + await rootMessenger.call('RampsController:setUserRegion', 'us-ca'); expect(controller.state.userRegion?.regionCode).toBe('us-ca'); expect(controller.state.userRegion?.country.name).toBe( @@ -2255,10 +2390,10 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { - await expect(controller.setUserRegion('xx')).rejects.toThrow( - 'Region "xx" not found in countries data', - ); + async ({ controller, rootMessenger }) => { + await expect( + rootMessenger.call('RampsController:setUserRegion', 'xx'), + ).rejects.toThrow('Region "xx" not found in countries data'); expect(controller.state.userRegion).toBeNull(); }, @@ -2266,8 +2401,10 @@ describe('RampsController', () => { }); it('throws error when countries are not in state', async () => { - await withController(async ({ controller }) => { - await expect(controller.setUserRegion('us-ca')).rejects.toThrow( + await withController(async ({ controller, rootMessenger }) => { + await expect( + rootMessenger.call('RampsController:setUserRegion', 'us-ca'), + ).rejects.toThrow( 'No countries found. Cannot set user region without valid country information.', ); @@ -2286,8 +2423,10 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { - await expect(controller.setUserRegion('FR')).rejects.toThrow( + async ({ controller, rootMessenger }) => { + await expect( + rootMessenger.call('RampsController:setUserRegion', 'FR'), + ).rejects.toThrow( 'No countries found. Cannot set user region without valid country information.', ); @@ -2334,7 +2473,7 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await controller.setUserRegion('us-ny'); + await rootMessenger.call('RampsController:setUserRegion', 'us-ny'); expect(controller.state.userRegion?.regionCode).toBe('us-ny'); expect(controller.state.userRegion?.country.isoCode).toBe('US'); @@ -2380,7 +2519,7 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await controller.setUserRegion('us-ca'); + await rootMessenger.call('RampsController:setUserRegion', 'us-ca'); expect(controller.state.userRegion?.regionCode).toBe('us-ca'); expect(controller.state.userRegion?.country.isoCode).toBe('US'); @@ -2431,7 +2570,7 @@ describe('RampsController', () => { async () => ({ providers: [] }), ); - await controller.setUserRegion('us-xx'); + await rootMessenger.call('RampsController:setUserRegion', 'us-xx'); expect(controller.state.userRegion?.regionCode).toBe('us-xx'); expect(controller.state.userRegion?.country.isoCode).toBe('US'); @@ -2488,7 +2627,10 @@ describe('RampsController', () => { expect(controller.state.providers.selected).toBeNull(); - controller.setSelectedProvider(mockProvider.id); + rootMessenger.call( + 'RampsController:setSelectedProvider', + mockProvider.id, + ); expect(controller.state.providers.selected).toStrictEqual( mockProvider, @@ -2519,7 +2661,7 @@ describe('RampsController', () => { }, }, }, - ({ controller }) => { + ({ controller, rootMessenger }) => { expect(controller.state.providers.selected).toStrictEqual( mockProvider, ); @@ -2530,7 +2672,7 @@ describe('RampsController', () => { mockPaymentMethod, ); - controller.setSelectedProvider(null); + rootMessenger.call('RampsController:setSelectedProvider', null); expect(controller.state.providers.selected).toBeNull(); expect(controller.state.paymentMethods.data).toStrictEqual([]); @@ -2550,9 +2692,12 @@ describe('RampsController', () => { }, }, }, - ({ controller }) => { + ({ rootMessenger }) => { expect(() => { - controller.setSelectedProvider(mockProvider.id); + rootMessenger.call( + 'RampsController:setSelectedProvider', + mockProvider.id, + ); }).toThrow( 'Region is required. Cannot proceed without valid region information.', ); @@ -2569,9 +2714,12 @@ describe('RampsController', () => { }, }, }, - ({ controller }) => { + ({ rootMessenger }) => { expect(() => { - controller.setSelectedProvider(mockProvider.id); + rootMessenger.call( + 'RampsController:setSelectedProvider', + mockProvider.id, + ); }).toThrow( 'Providers not loaded. Cannot set selected provider before providers are fetched.', ); @@ -2589,9 +2737,12 @@ describe('RampsController', () => { }, }, }, - ({ controller }) => { + ({ rootMessenger }) => { expect(() => { - controller.setSelectedProvider('/providers/nonexistent'); + rootMessenger.call( + 'RampsController:setSelectedProvider', + '/providers/nonexistent', + ); }).toThrow( 'Provider with ID "/providers/nonexistent" not found in available providers.', ); @@ -2643,7 +2794,10 @@ describe('RampsController', () => { existingPaymentMethod, ); - controller.setSelectedProvider(newProvider.id); + rootMessenger.call( + 'RampsController:setSelectedProvider', + newProvider.id, + ); expect(controller.state.providers.selected).toStrictEqual( newProvider, @@ -2688,13 +2842,16 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getPaymentMethods', getPaymentMethodsMock, ); - controller.setSelectedProvider(providerWithExclusion.id); + rootMessenger.call( + 'RampsController:setSelectedProvider', + providerWithExclusion.id, + ); expect(getPaymentMethodsMock).not.toHaveBeenCalled(); }, @@ -2717,13 +2874,16 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getPaymentMethods', getPaymentMethodsMock, ); - controller.setSelectedProvider(providerWithoutField.id); + rootMessenger.call( + 'RampsController:setSelectedProvider', + providerWithoutField.id, + ); await new Promise((resolve) => setTimeout(resolve, 0)); @@ -2762,13 +2922,16 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getPaymentMethods', getPaymentMethodsMock, ); - controller.setSelectedProvider(providerWithSupport.id); + rootMessenger.call( + 'RampsController:setSelectedProvider', + providerWithSupport.id, + ); await new Promise((resolve) => setTimeout(resolve, 0)); @@ -2820,7 +2983,10 @@ describe('RampsController', () => { expect(controller.state.tokens.selected).toBeNull(); - controller.setSelectedToken(mockToken.assetId); + rootMessenger.call( + 'RampsController:setSelectedToken', + mockToken.assetId, + ); expect(controller.state.tokens.selected).toStrictEqual(mockToken); }, @@ -2841,12 +3007,12 @@ describe('RampsController', () => { }, }, }, - ({ controller }) => { + ({ controller, rootMessenger }) => { expect(controller.state.tokens.selected).toStrictEqual(mockToken); expect(controller.state.paymentMethods.data).toHaveLength(1); expect(controller.state.paymentMethods.selected).not.toBeNull(); - controller.setSelectedToken(undefined); + rootMessenger.call('RampsController:setSelectedToken', undefined); expect(controller.state.tokens.selected).toBeNull(); expect(controller.state.paymentMethods.data).toStrictEqual([]); @@ -2866,8 +3032,13 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { - expect(() => controller.setSelectedToken(mockToken.assetId)).toThrow( + async ({ rootMessenger }) => { + expect(() => + rootMessenger.call( + 'RampsController:setSelectedToken', + mockToken.assetId, + ), + ).toThrow( 'Region is required. Cannot proceed without valid region information.', ); }, @@ -2883,8 +3054,13 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { - expect(() => controller.setSelectedToken(mockToken.assetId)).toThrow( + async ({ rootMessenger }) => { + expect(() => + rootMessenger.call( + 'RampsController:setSelectedToken', + mockToken.assetId, + ), + ).toThrow( 'Tokens not loaded. Cannot set selected token before tokens are fetched.', ); }, @@ -2901,9 +3077,12 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { + async ({ rootMessenger }) => { expect(() => - controller.setSelectedToken('eip155:1/erc20:0xNONEXISTENT'), + rootMessenger.call( + 'RampsController:setSelectedToken', + 'eip155:1/erc20:0xNONEXISTENT', + ), ).toThrow( 'Token with asset ID "eip155:1/erc20:0xNONEXISTENT" not found in available tokens.', ); @@ -2921,7 +3100,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let receivedAssetId: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getPaymentMethods', @@ -2936,7 +3115,10 @@ describe('RampsController', () => { }, ); - controller.setSelectedToken(mockToken.assetId); + rootMessenger.call( + 'RampsController:setSelectedToken', + mockToken.assetId, + ); await new Promise((resolve) => setTimeout(resolve, 10)); expect(receivedAssetId).toBe(mockToken.assetId); @@ -2983,7 +3165,10 @@ describe('RampsController', () => { mockPaymentMethod, ); - controller.setSelectedToken(newToken.assetId); + rootMessenger.call( + 'RampsController:setSelectedToken', + newToken.assetId, + ); expect(controller.state.tokens.selected).toStrictEqual(newToken); expect(controller.state.paymentMethods.data).toStrictEqual([]); @@ -3041,7 +3226,11 @@ describe('RampsController', () => { expect(controller.state.tokens.data).toBeNull(); - const tokens = await controller.getTokens('us-ca', 'buy'); + const tokens = await rootMessenger.call( + 'RampsController:getTokens', + 'us-ca', + 'buy', + ); expect(tokens).toMatchInlineSnapshot(` { @@ -3083,7 +3272,7 @@ describe('RampsController', () => { }); it('fetches tokens with sell action', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let receivedAction: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3097,14 +3286,14 @@ describe('RampsController', () => { }, ); - await controller.getTokens('us-ca', 'sell'); + await rootMessenger.call('RampsController:getTokens', 'us-ca', 'sell'); expect(receivedAction).toBe('sell'); }); }); it('uses default buy action when no argument is provided', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let receivedAction: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3118,14 +3307,14 @@ describe('RampsController', () => { }, ); - await controller.getTokens('us-ca'); + await rootMessenger.call('RampsController:getTokens', 'us-ca'); expect(receivedAction).toBe('buy'); }); }); it('normalizes region case when calling service', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let receivedRegion: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3139,14 +3328,14 @@ describe('RampsController', () => { }, ); - await controller.getTokens('US-ca', 'buy'); + await rootMessenger.call('RampsController:getTokens', 'US-ca', 'buy'); expect(receivedRegion).toBe('us-ca'); }); }); it('creates separate cache entries for different actions', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let callCount = 0; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3160,15 +3349,15 @@ describe('RampsController', () => { }, ); - await controller.getTokens('us-ca', 'buy'); - await controller.getTokens('us-ca', 'sell'); + await rootMessenger.call('RampsController:getTokens', 'us-ca', 'buy'); + await rootMessenger.call('RampsController:getTokens', 'us-ca', 'sell'); expect(callCount).toBe(2); }); }); it('creates separate cache entries for different regions', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let callCount = 0; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3182,8 +3371,8 @@ describe('RampsController', () => { }, ); - await controller.getTokens('us-ca', 'buy'); - await controller.getTokens('fr', 'buy'); + await rootMessenger.call('RampsController:getTokens', 'us-ca', 'buy'); + await rootMessenger.call('RampsController:getTokens', 'fr', 'buy'); expect(callCount).toBe(2); }); @@ -3198,7 +3387,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let receivedRegion: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3212,7 +3401,11 @@ describe('RampsController', () => { }, ); - await controller.getTokens(undefined, 'buy'); + await rootMessenger.call( + 'RampsController:getTokens', + undefined, + 'buy', + ); expect(receivedRegion).toBe('fr'); }, @@ -3220,8 +3413,10 @@ describe('RampsController', () => { }); it('throws error when region is not provided and userRegion is not set', async () => { - await withController(async ({ controller }) => { - await expect(controller.getTokens(undefined, 'buy')).rejects.toThrow( + await withController(async ({ rootMessenger }) => { + await expect( + rootMessenger.call('RampsController:getTokens', undefined, 'buy'), + ).rejects.toThrow( 'Region is required. Cannot proceed without valid region information.', ); }); @@ -3237,7 +3432,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let serviceCalled = false; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3247,7 +3442,11 @@ describe('RampsController', () => { }, ); - const result = await controller.getTokens('us-ca', 'buy'); + const result = await rootMessenger.call( + 'RampsController:getTokens', + 'us-ca', + 'buy', + ); expect(serviceCalled).toBe(true); expect(result).toStrictEqual(mockTokens); @@ -3265,7 +3464,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let serviceCalled = false; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3275,7 +3474,12 @@ describe('RampsController', () => { }, ); - await controller.getTokens('us-ca', 'buy', { provider: 'moonpay' }); + await rootMessenger.call( + 'RampsController:getTokens', + 'us-ca', + 'buy', + { provider: 'moonpay' }, + ); expect(serviceCalled).toBe(true); }, @@ -3291,7 +3495,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let receivedRegion: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3305,7 +3509,7 @@ describe('RampsController', () => { }, ); - await controller.getTokens('us-ca', 'buy'); + await rootMessenger.call('RampsController:getTokens', 'us-ca', 'buy'); expect(receivedRegion).toBe('us-ca'); }, @@ -3337,7 +3541,7 @@ describe('RampsController', () => { expect(controller.state.userRegion?.regionCode).toBe('us-ca'); expect(controller.state.tokens.data).toBeNull(); - await controller.getTokens('US-ca'); + await rootMessenger.call('RampsController:getTokens', 'US-ca'); expect(controller.state.tokens.data).toStrictEqual(mockTokens); }, @@ -3395,7 +3599,7 @@ describe('RampsController', () => { expect(controller.state.userRegion?.regionCode).toBe('us-ca'); expect(controller.state.tokens.data).toStrictEqual(existingTokens); - await controller.getTokens('fr'); + await rootMessenger.call('RampsController:getTokens', 'fr'); expect(controller.state.tokens.data).toStrictEqual(existingTokens); }, @@ -3403,7 +3607,7 @@ describe('RampsController', () => { }); it('passes provider parameter to service', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let receivedProvider: string | string[] | undefined; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3417,14 +3621,16 @@ describe('RampsController', () => { }, ); - await controller.getTokens('us-ca', 'buy', { provider: 'provider-id' }); + await rootMessenger.call('RampsController:getTokens', 'us-ca', 'buy', { + provider: 'provider-id', + }); expect(receivedProvider).toBe('provider-id'); }); }); it('creates separate cache entries for different providers', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let callCount = 0; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3438,15 +3644,19 @@ describe('RampsController', () => { }, ); - await controller.getTokens('us-ca', 'buy', { provider: 'provider-1' }); - await controller.getTokens('us-ca', 'buy', { provider: 'provider-2' }); + await rootMessenger.call('RampsController:getTokens', 'us-ca', 'buy', { + provider: 'provider-1', + }); + await rootMessenger.call('RampsController:getTokens', 'us-ca', 'buy', { + provider: 'provider-2', + }); expect(callCount).toBe(2); }); }); it('creates separate cache entries for requests with and without provider', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { let callCount = 0; rootMessenger.registerActionHandler( 'RampsService:getTokens', @@ -3460,8 +3670,10 @@ describe('RampsController', () => { }, ); - await controller.getTokens('us-ca', 'buy'); - await controller.getTokens('us-ca', 'buy', { provider: 'provider-1' }); + await rootMessenger.call('RampsController:getTokens', 'us-ca', 'buy'); + await rootMessenger.call('RampsController:getTokens', 'us-ca', 'buy', { + provider: 'provider-1', + }); expect(callCount).toBe(2); }); @@ -3539,10 +3751,14 @@ describe('RampsController', () => { mockPaymentMethod1, ); - await controller.getPaymentMethods('us-ca', { - assetId: 'eip155:1/slip44:60', - provider: '/providers/stripe', - }); + await rootMessenger.call( + 'RampsController:getPaymentMethods', + 'us-ca', + { + assetId: 'eip155:1/slip44:60', + provider: '/providers/stripe', + }, + ); expect(controller.state.paymentMethods.selected).toStrictEqual( mockPaymentMethod1, @@ -3588,10 +3804,14 @@ describe('RampsController', () => { removedPaymentMethod, ); - await controller.getPaymentMethods('us-ca', { - assetId: 'eip155:1/slip44:60', - provider: '/providers/stripe', - }); + await rootMessenger.call( + 'RampsController:getPaymentMethods', + 'us-ca', + { + assetId: 'eip155:1/slip44:60', + provider: '/providers/stripe', + }, + ); expect(controller.state.paymentMethods.selected).toStrictEqual( mockPaymentMethod1, @@ -3624,10 +3844,14 @@ describe('RampsController', () => { expect(controller.state.paymentMethods.selected).toBeNull(); - await controller.getPaymentMethods('us-ca', { - assetId: 'eip155:1/slip44:60', - provider: '/providers/stripe', - }); + await rootMessenger.call( + 'RampsController:getPaymentMethods', + 'us-ca', + { + assetId: 'eip155:1/slip44:60', + provider: '/providers/stripe', + }, + ); expect(controller.state.paymentMethods.selected).toStrictEqual( mockPaymentMethod1, @@ -3659,10 +3883,14 @@ describe('RampsController', () => { expect(controller.state.paymentMethods.data).toStrictEqual([]); - await controller.getPaymentMethods('us-ca', { - assetId: 'eip155:1/slip44:60', - provider: '/providers/stripe', - }); + await rootMessenger.call( + 'RampsController:getPaymentMethods', + 'us-ca', + { + assetId: 'eip155:1/slip44:60', + provider: '/providers/stripe', + }, + ); expect(controller.state.paymentMethods.data).toStrictEqual([ mockPaymentMethod1, @@ -3681,7 +3909,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let receivedRegion: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getPaymentMethods', @@ -3696,7 +3924,7 @@ describe('RampsController', () => { }, ); - await controller.getPaymentMethods('fr', { + await rootMessenger.call('RampsController:getPaymentMethods', 'fr', { assetId: 'eip155:1/slip44:60', provider: '/providers/stripe', }); @@ -3728,9 +3956,9 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { + async ({ rootMessenger }) => { await expect( - controller.getPaymentMethods('us-ca', { + rootMessenger.call('RampsController:getPaymentMethods', 'us-ca', { assetId: 'eip155:1/slip44:60', provider: '/providers/stripe', }), @@ -3761,7 +3989,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let receivedAssetId: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getPaymentMethods', @@ -3776,9 +4004,13 @@ describe('RampsController', () => { }, ); - await controller.getPaymentMethods('us-ca', { - provider: '/providers/stripe', - }); + await rootMessenger.call( + 'RampsController:getPaymentMethods', + 'us-ca', + { + provider: '/providers/stripe', + }, + ); expect(receivedAssetId).toBe(mockToken.assetId); }, @@ -3810,7 +4042,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let receivedProvider: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getPaymentMethods', @@ -3825,9 +4057,13 @@ describe('RampsController', () => { }, ); - await controller.getPaymentMethods('us-ca', { - assetId: 'eip155:1/slip44:60', - }); + await rootMessenger.call( + 'RampsController:getPaymentMethods', + 'us-ca', + { + assetId: 'eip155:1/slip44:60', + }, + ); expect(receivedProvider).toBe(testProvider.id); }, @@ -3843,7 +4079,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let receivedRegion: string | undefined; rootMessenger.registerActionHandler( 'RampsService:getPaymentMethods', @@ -3858,10 +4094,14 @@ describe('RampsController', () => { }, ); - await controller.getPaymentMethods(undefined, { - assetId: 'eip155:1/slip44:60', - provider: '/providers/stripe', - }); + await rootMessenger.call( + 'RampsController:getPaymentMethods', + undefined, + { + assetId: 'eip155:1/slip44:60', + provider: '/providers/stripe', + }, + ); expect(receivedRegion).toBe('fr'); }, @@ -3897,10 +4137,14 @@ describe('RampsController', () => { async () => ({ payments: [] }), ); - await controller.getPaymentMethods('us-ca', { - assetId: 'eip155:1/slip44:60', - provider: '/providers/stripe', - }); + await rootMessenger.call( + 'RampsController:getPaymentMethods', + 'us-ca', + { + assetId: 'eip155:1/slip44:60', + provider: '/providers/stripe', + }, + ); expect(controller.state.paymentMethods.selected).toBeNull(); expect(controller.state.paymentMethods.data).toStrictEqual([]); @@ -3909,9 +4153,9 @@ describe('RampsController', () => { }); it('throws error when region is not provided and userRegion is not set', async () => { - await withController(async ({ controller }) => { + await withController(async ({ rootMessenger }) => { await expect( - controller.getPaymentMethods(undefined, { + rootMessenger.call('RampsController:getPaymentMethods', undefined, { assetId: 'eip155:1/slip44:60', provider: '/providers/stripe', }), @@ -3932,7 +4176,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let receivedAssetId: string | undefined; let receivedProvider: string | undefined; rootMessenger.registerActionHandler( @@ -3949,7 +4193,10 @@ describe('RampsController', () => { }, ); - await controller.getPaymentMethods('us-ca'); + await rootMessenger.call( + 'RampsController:getPaymentMethods', + 'us-ca', + ); expect(receivedAssetId).toBe(''); expect(receivedProvider).toBe(''); @@ -4039,14 +4286,18 @@ describe('RampsController', () => { }, ); - const tokenAPaymentMethodsPromise = controller.getPaymentMethods( + const tokenAPaymentMethodsPromise = rootMessenger.call( + 'RampsController:getPaymentMethods', 'us-ca', { assetId: tokenA.assetId, }, ); - controller.setSelectedToken(tokenB.assetId); + rootMessenger.call( + 'RampsController:setSelectedToken', + tokenB.assetId, + ); resolveTokenARequest({ payments: paymentMethodsForTokenA }); await tokenAPaymentMethodsPromise; @@ -4147,14 +4398,18 @@ describe('RampsController', () => { }, ); - const providerAPaymentMethodsPromise = controller.getPaymentMethods( + const providerAPaymentMethodsPromise = rootMessenger.call( + 'RampsController:getPaymentMethods', 'us-ca', { provider: providerA.id, }, ); - controller.setSelectedProvider(providerB.id); + rootMessenger.call( + 'RampsController:setSelectedProvider', + providerB.id, + ); resolveProviderARequest({ payments: paymentMethodsForProviderA }); await providerAPaymentMethodsPromise; @@ -4222,10 +4477,14 @@ describe('RampsController', () => { async () => ({ payments: newPaymentMethods }), ); - await controller.getPaymentMethods('us-ca', { - assetId: token.assetId, - provider: provider.id, - }); + await rootMessenger.call( + 'RampsController:getPaymentMethods', + 'us-ca', + { + assetId: token.assetId, + provider: provider.id, + }, + ); expect(controller.state.tokens.selected).toStrictEqual(token); expect(controller.state.providers.selected).toStrictEqual(provider); @@ -4255,10 +4514,13 @@ describe('RampsController', () => { }, }, }, - ({ controller }) => { + ({ controller, rootMessenger }) => { expect(controller.state.paymentMethods.selected).toBeNull(); - controller.setSelectedPaymentMethod(mockPaymentMethod.id); + rootMessenger.call( + 'RampsController:setSelectedPaymentMethod', + mockPaymentMethod.id, + ); expect(controller.state.paymentMethods.selected).toStrictEqual( mockPaymentMethod, @@ -4279,12 +4541,15 @@ describe('RampsController', () => { }, }, }, - ({ controller }) => { + ({ controller, rootMessenger }) => { expect(controller.state.paymentMethods.selected).toStrictEqual( mockPaymentMethod, ); - controller.setSelectedPaymentMethod(undefined); + rootMessenger.call( + 'RampsController:setSelectedPaymentMethod', + undefined, + ); expect(controller.state.paymentMethods.selected).toBeNull(); }, @@ -4292,9 +4557,12 @@ describe('RampsController', () => { }); it('throws error when payment methods are not loaded', async () => { - await withController(({ controller }) => { + await withController(({ rootMessenger }) => { expect(() => { - controller.setSelectedPaymentMethod(mockPaymentMethod.id); + rootMessenger.call( + 'RampsController:setSelectedPaymentMethod', + mockPaymentMethod.id, + ); }).toThrow( 'Payment methods not loaded. Cannot set selected payment method before payment methods are fetched.', ); @@ -4310,9 +4578,12 @@ describe('RampsController', () => { }, }, }, - ({ controller }) => { + ({ rootMessenger }) => { expect(() => { - controller.setSelectedPaymentMethod('/payments/nonexistent'); + rootMessenger.call( + 'RampsController:setSelectedPaymentMethod', + '/payments/nonexistent', + ); }).toThrow( 'Payment method with ID "/payments/nonexistent" not found in available payment methods.', ); @@ -4372,13 +4643,13 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getQuotes', async () => mockQuotesResponse, ); - const result = await controller.getQuotes({ + const result = await rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4423,7 +4694,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getQuotes', async (params) => { @@ -4432,7 +4703,7 @@ describe('RampsController', () => { }, ); - const result = await controller.getQuotes({ + const result = await rootMessenger.call('RampsController:getQuotes', { amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', }); @@ -4463,7 +4734,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getQuotes', async (params) => { @@ -4473,7 +4744,7 @@ describe('RampsController', () => { }, ); - await controller.getQuotes({ + await rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4483,9 +4754,9 @@ describe('RampsController', () => { }); it('throws when region is not provided and not in state', async () => { - await withController(async ({ controller }) => { + await withController(async ({ rootMessenger }) => { await expect( - controller.getQuotes({ + rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4515,9 +4786,9 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { + async ({ rootMessenger }) => { await expect( - controller.getQuotes({ + rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4538,9 +4809,9 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { + async ({ rootMessenger }) => { await expect( - controller.getQuotes({ + rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4571,9 +4842,9 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { + async ({ rootMessenger }) => { await expect( - controller.getQuotes({ + rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 0, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4581,7 +4852,7 @@ describe('RampsController', () => { ).rejects.toThrow('Amount must be a positive finite number'); await expect( - controller.getQuotes({ + rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: -100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4589,7 +4860,7 @@ describe('RampsController', () => { ).rejects.toThrow('Amount must be a positive finite number'); await expect( - controller.getQuotes({ + rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: Infinity, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4620,9 +4891,9 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { + async ({ rootMessenger }) => { await expect( - controller.getQuotes({ + rootMessenger.call('RampsController:getQuotes', { assetId: '', amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4630,7 +4901,7 @@ describe('RampsController', () => { ).rejects.toThrow('assetId is required'); await expect( - controller.getQuotes({ + rootMessenger.call('RampsController:getQuotes', { assetId: ' ', amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4661,9 +4932,9 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { + async ({ rootMessenger }) => { await expect( - controller.getQuotes({ + rootMessenger.call('RampsController:getQuotes', { amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', }), @@ -4693,9 +4964,9 @@ describe('RampsController', () => { }, }, }, - async ({ controller }) => { + async ({ rootMessenger }) => { await expect( - controller.getQuotes({ + rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 100, walletAddress: '', @@ -4703,7 +4974,7 @@ describe('RampsController', () => { ).rejects.toThrow('walletAddress is required'); await expect( - controller.getQuotes({ + rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 100, walletAddress: ' ', @@ -4734,7 +5005,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let callCount = 0; rootMessenger.registerActionHandler( 'RampsService:getQuotes', @@ -4744,12 +5015,12 @@ describe('RampsController', () => { }, ); - await controller.getQuotes({ + await rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', }); - await controller.getQuotes({ + await rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4761,7 +5032,7 @@ describe('RampsController', () => { }); it('accepts explicit region and fiat parameters', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getQuotes', async (params) => { @@ -4771,7 +5042,7 @@ describe('RampsController', () => { }, ); - await controller.getQuotes({ + await rootMessenger.call('RampsController:getQuotes', { region: 'fr', fiat: 'eur', assetId: 'eip155:1/slip44:60', @@ -4803,7 +5074,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getQuotes', async (params) => { @@ -4815,7 +5086,7 @@ describe('RampsController', () => { }, ); - await controller.getQuotes({ + await rootMessenger.call('RampsController:getQuotes', { assetId: ' eip155:1/slip44:60 ', amount: 100, walletAddress: ' 0x1234567890abcdef1234567890abcdef12345678 ', @@ -4845,7 +5116,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let capturedProviders: string[] | undefined; rootMessenger.registerActionHandler( 'RampsService:getQuotes', @@ -4855,7 +5126,7 @@ describe('RampsController', () => { }, ); - await controller.getQuotes({ + await rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4923,7 +5194,7 @@ describe('RampsController', () => { }, }, }, - async ({ controller, rootMessenger }) => { + async ({ rootMessenger }) => { let capturedProviders: string[] | undefined; rootMessenger.registerActionHandler( 'RampsService:getQuotes', @@ -4933,7 +5204,7 @@ describe('RampsController', () => { }, ); - await controller.getQuotes({ + await rootMessenger.call('RampsController:getQuotes', { assetId: 'eip155:1/slip44:60', amount: 100, walletAddress: '0x1234567890abcdef1234567890abcdef12345678', @@ -4951,7 +5222,7 @@ describe('RampsController', () => { describe('getBuyWidgetData', () => { it('fetches and returns widget URL via RampsService messenger', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const quote: Quote = { provider: '/providers/transak-staging', quote: { @@ -4972,7 +5243,10 @@ describe('RampsController', () => { }), ); - const buyWidget = await controller.getBuyWidgetData(quote); + const buyWidget = await rootMessenger.call( + 'RampsController:getBuyWidgetData', + quote, + ); expect(buyWidget).toStrictEqual({ url: 'https://global.transak.com/?apiKey=test', @@ -4983,7 +5257,7 @@ describe('RampsController', () => { }); it('returns null when buyURL is not present', async () => { - await withController(async ({ controller }) => { + await withController(async ({ rootMessenger }) => { const quote: Quote = { provider: '/providers/transak', quote: { @@ -4993,26 +5267,32 @@ describe('RampsController', () => { }, }; - const buyWidget = await controller.getBuyWidgetData(quote); + const buyWidget = await rootMessenger.call( + 'RampsController:getBuyWidgetData', + quote, + ); expect(buyWidget).toBeNull(); }); }); it('returns null when quote object is malformed', async () => { - await withController(async ({ controller }) => { + await withController(async ({ rootMessenger }) => { const quote = { provider: '/providers/moonpay', } as unknown as Quote; - const buyWidget = await controller.getBuyWidgetData(quote); + const buyWidget = await rootMessenger.call( + 'RampsController:getBuyWidgetData', + quote, + ); expect(buyWidget).toBeNull(); }); }); it('propagates error when service call throws', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const quote: Quote = { provider: '/providers/transak-staging', quote: { @@ -5031,14 +5311,14 @@ describe('RampsController', () => { }, ); - await expect(controller.getBuyWidgetData(quote)).rejects.toThrow( - 'Network error', - ); + await expect( + rootMessenger.call('RampsController:getBuyWidgetData', quote), + ).rejects.toThrow('Network error'); }); }); it('returns null when service returns BuyWidget with null url', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const quote: Quote = { provider: '/providers/transak-staging', quote: { @@ -5059,7 +5339,10 @@ describe('RampsController', () => { }), ); - const buyWidget = await controller.getBuyWidgetData(quote); + const buyWidget = await rootMessenger.call( + 'RampsController:getBuyWidgetData', + quote, + ); expect(buyWidget).toBeNull(); }); @@ -5068,8 +5351,8 @@ describe('RampsController', () => { describe('addPrecreatedOrder', () => { it('adds a stub order with Precreated status for polling', async () => { - await withController(({ controller }) => { - controller.addPrecreatedOrder({ + await withController(({ controller, rootMessenger }) => { + rootMessenger.call('RampsController:addPrecreatedOrder', { orderId: '/providers/paypal/orders/abc123', providerCode: 'paypal', walletAddress: '0xabc', @@ -5086,8 +5369,8 @@ describe('RampsController', () => { }); it('parses orderCode when orderId has no /orders/ segment', async () => { - await withController(({ controller }) => { - controller.addPrecreatedOrder({ + await withController(({ controller, rootMessenger }) => { + rootMessenger.call('RampsController:addPrecreatedOrder', { orderId: 'plain-order-id', providerCode: 'transak', walletAddress: '0xdef', @@ -5100,8 +5383,8 @@ describe('RampsController', () => { }); it('skips addOrder when orderId ends with /orders/ (empty orderCode)', async () => { - await withController(({ controller }) => { - controller.addPrecreatedOrder({ + await withController(({ controller, rootMessenger }) => { + rootMessenger.call('RampsController:addPrecreatedOrder', { orderId: '/providers/paypal/orders/', providerCode: 'paypal', walletAddress: '0xabc', @@ -5114,13 +5397,13 @@ describe('RampsController', () => { describe('destroy', () => { it('clears stateChange subscriptions so listeners stop firing', async () => { - await withController(({ controller, messenger }) => { + await withController(({ controller, rootMessenger, messenger }) => { const listener = jest.fn(); messenger.subscribe('RampsController:stateChange', listener); controller.destroy(); - controller.setSelectedProvider(null); + rootMessenger.call('RampsController:setSelectedProvider', null); expect(listener).not.toHaveBeenCalled(); }); @@ -5163,19 +5446,19 @@ describe('RampsController', () => { }; it('adds a new order to state', async () => { - await withController(({ controller }) => { - controller.addOrder(mockOrder); + await withController(({ controller, rootMessenger }) => { + rootMessenger.call('RampsController:addOrder', mockOrder); expect(controller.state.orders).toHaveLength(1); expect(controller.state.orders[0]).toStrictEqual(mockOrder); }); }); it('merges an existing order with the same providerOrderId', async () => { - await withController(({ controller }) => { - controller.addOrder(mockOrder); + await withController(({ controller, rootMessenger }) => { + rootMessenger.call('RampsController:addOrder', mockOrder); const updatedOrder = { ...mockOrder, fiatAmount: 200 }; - controller.addOrder(updatedOrder); + rootMessenger.call('RampsController:addOrder', updatedOrder); expect(controller.state.orders).toHaveLength(1); expect(controller.state.orders[0]?.fiatAmount).toBe(200); @@ -5183,7 +5466,7 @@ describe('RampsController', () => { }); it('preserves existing fields not present in the update', async () => { - await withController(({ controller }) => { + await withController(({ controller, rootMessenger }) => { const orderWithPaymentDetails = createMockOrder({ providerOrderId: 'abc-123', paymentDetails: [ @@ -5196,13 +5479,13 @@ describe('RampsController', () => { }, ], }); - controller.addOrder(orderWithPaymentDetails); + rootMessenger.call('RampsController:addOrder', orderWithPaymentDetails); const apiUpdate = createMockOrder({ providerOrderId: 'abc-123', status: RampsOrderStatus.Pending, }); - controller.addOrder(apiUpdate); + rootMessenger.call('RampsController:addOrder', apiUpdate); expect(controller.state.orders).toHaveLength(1); expect(controller.state.orders[0]?.status).toBe( @@ -5219,9 +5502,9 @@ describe('RampsController', () => { }); it('adds orders with different providerOrderIds independently', async () => { - await withController(({ controller }) => { - controller.addOrder(mockOrder); - controller.addOrder({ + await withController(({ controller, rootMessenger }) => { + rootMessenger.call('RampsController:addOrder', mockOrder); + rootMessenger.call('RampsController:addOrder', { ...mockOrder, providerOrderId: 'def-456', }); @@ -5233,22 +5516,22 @@ describe('RampsController', () => { describe('removeOrder', () => { it('removes an order from state by providerOrderId', async () => { - await withController(({ controller }) => { + await withController(({ controller, rootMessenger }) => { const order = createMockOrder({ providerOrderId: 'abc-123' }); - controller.addOrder(order); + rootMessenger.call('RampsController:addOrder', order); expect(controller.state.orders).toHaveLength(1); - controller.removeOrder('abc-123'); + rootMessenger.call('RampsController:removeOrder', 'abc-123'); expect(controller.state.orders).toHaveLength(0); }); }); it('does nothing when providerOrderId is not found', async () => { - await withController(({ controller }) => { + await withController(({ controller, rootMessenger }) => { const order = createMockOrder({ providerOrderId: 'abc-123' }); - controller.addOrder(order); + rootMessenger.call('RampsController:addOrder', order); - controller.removeOrder('nonexistent'); + rootMessenger.call('RampsController:removeOrder', 'nonexistent'); expect(controller.state.orders).toHaveLength(1); }); }); @@ -5290,13 +5573,14 @@ describe('RampsController', () => { }; it('fetches order via RampsService messenger', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getOrder', async () => mockOrder, ); - const order = await controller.getOrder( + const order = await rootMessenger.call( + 'RampsController:getOrder', 'transak-staging', 'abc-123', '0xabc', @@ -5312,7 +5596,7 @@ describe('RampsController', () => { providerOrderId: 'abc-123', status: RampsOrderStatus.Pending, }); - controller.addOrder(existingOrder); + rootMessenger.call('RampsController:addOrder', existingOrder); const updatedOrder = { ...mockOrder, @@ -5323,7 +5607,12 @@ describe('RampsController', () => { async () => updatedOrder, ); - await controller.getOrder('transak-staging', 'abc-123', '0xabc'); + await rootMessenger.call( + 'RampsController:getOrder', + 'transak-staging', + 'abc-123', + '0xabc', + ); expect(controller.state.orders).toHaveLength(1); expect(controller.state.orders[0]?.status).toBe( @@ -5341,7 +5630,12 @@ describe('RampsController', () => { expect(controller.state.orders).toHaveLength(0); - await controller.getOrder('transak-staging', 'abc-123', '0xabc'); + await rootMessenger.call( + 'RampsController:getOrder', + 'transak-staging', + 'abc-123', + '0xabc', + ); expect(controller.state.orders).toHaveLength(1); expect(controller.state.orders[0]?.providerOrderId).toBe('abc-123'); @@ -5366,7 +5660,7 @@ describe('RampsController', () => { }, ], }); - controller.addOrder(existingOrder); + rootMessenger.call('RampsController:addOrder', existingOrder); const apiResponse = createMockOrder({ providerOrderId: 'abc-123', @@ -5377,7 +5671,12 @@ describe('RampsController', () => { async () => apiResponse, ); - await controller.getOrder('transak-staging', 'abc-123', '0xabc'); + await rootMessenger.call( + 'RampsController:getOrder', + 'transak-staging', + 'abc-123', + '0xabc', + ); expect(controller.state.orders).toHaveLength(1); expect(controller.state.orders[0]?.status).toBe( @@ -5430,13 +5729,14 @@ describe('RampsController', () => { }; it('fetches order from callback URL via RampsService messenger', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'RampsService:getOrderFromCallback', async () => mockOrder, ); - const order = await controller.getOrderFromCallback( + const order = await rootMessenger.call( + 'RampsController:getOrderFromCallback', 'transak-staging', 'https://metamask.app.link/on-ramp?orderId=abc-123', '0xabc', @@ -5464,7 +5764,7 @@ describe('RampsController', () => { provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(pendingOrder); + rootMessenger.call('RampsController:addOrder', pendingOrder); const updatedOrder = { ...pendingOrder, @@ -5475,19 +5775,19 @@ describe('RampsController', () => { async () => updatedOrder, ); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(controller.state.orders[0]?.status).toBe( RampsOrderStatus.Completed, ); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('startOrderPolling is idempotent', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const handler = jest.fn(async () => createMockOrder({ providerOrderId: 'p1', @@ -5496,28 +5796,28 @@ describe('RampsController', () => { ); rootMessenger.registerActionHandler('RampsService:getOrder', handler); - controller.startOrderPolling(); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); + rootMessenger.call('RampsController:startOrderPolling'); expect(handler).not.toHaveBeenCalled(); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('stopOrderPolling clears the polling timer', async () => { - await withController(async ({ controller }) => { - controller.startOrderPolling(); - controller.stopOrderPolling(); - controller.stopOrderPolling(); + await withController(async ({ controller, rootMessenger }) => { + rootMessenger.call('RampsController:startOrderPolling'); + rootMessenger.call('RampsController:stopOrderPolling'); + rootMessenger.call('RampsController:stopOrderPolling'); expect(controller.state.orders).toStrictEqual([]); }); }); it('destroy stops order polling', async () => { - await withController(async ({ controller }) => { - controller.startOrderPolling(); + await withController(async ({ controller, rootMessenger }) => { + rootMessenger.call('RampsController:startOrderPolling'); controller.destroy(); expect(controller.state.orders).toStrictEqual([]); @@ -5525,14 +5825,14 @@ describe('RampsController', () => { }); it('publishes orderStatusChanged when order status transitions', async () => { - await withController(async ({ controller, rootMessenger, messenger }) => { + await withController(async ({ rootMessenger, messenger }) => { const pendingOrder = createMockOrder({ providerOrderId: 'status-change-1', status: RampsOrderStatus.Pending, provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(pendingOrder); + rootMessenger.call('RampsController:addOrder', pendingOrder); const updatedOrder = { ...pendingOrder, @@ -5549,7 +5849,7 @@ describe('RampsController', () => { statusChangedListener, ); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(statusChangedListener).toHaveBeenCalledWith({ @@ -5557,19 +5857,19 @@ describe('RampsController', () => { previousStatus: RampsOrderStatus.Pending, }); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('does not publish orderStatusChanged when status stays the same', async () => { - await withController(async ({ controller, rootMessenger, messenger }) => { + await withController(async ({ rootMessenger, messenger }) => { const pendingOrder = createMockOrder({ providerOrderId: 'no-change-1', status: RampsOrderStatus.Pending, provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(pendingOrder); + rootMessenger.call('RampsController:addOrder', pendingOrder); rootMessenger.registerActionHandler( 'RampsService:getOrder', @@ -5582,12 +5882,12 @@ describe('RampsController', () => { statusChangedListener, ); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(statusChangedListener).not.toHaveBeenCalled(); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); @@ -5599,7 +5899,7 @@ describe('RampsController', () => { provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(pendingOrder); + rootMessenger.call('RampsController:addOrder', pendingOrder); const completedOrder = { ...pendingOrder, @@ -5610,14 +5910,14 @@ describe('RampsController', () => { async () => completedOrder, ); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(controller.state.orders[0]?.status).toBe( RampsOrderStatus.Completed, ); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); @@ -5629,7 +5929,7 @@ describe('RampsController', () => { provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(pendingOrder); + rootMessenger.call('RampsController:addOrder', pendingOrder); const unknownOrder = { ...pendingOrder, @@ -5640,14 +5940,14 @@ describe('RampsController', () => { async () => unknownOrder, ); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(controller.state.orders[0]?.status).toBe( RampsOrderStatus.Unknown, ); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); @@ -5659,7 +5959,7 @@ describe('RampsController', () => { provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(pendingOrder); + rootMessenger.call('RampsController:addOrder', pendingOrder); rootMessenger.registerActionHandler( 'RampsService:getOrder', @@ -5668,92 +5968,92 @@ describe('RampsController', () => { }, ); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(controller.state.orders[0]?.status).toBe( RampsOrderStatus.Pending, ); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('skips orders without provider code or wallet address', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const orderWithoutProvider = createMockOrder({ providerOrderId: 'no-provider-1', status: RampsOrderStatus.Pending, provider: undefined, walletAddress: '0xabc', }); - controller.addOrder(orderWithoutProvider); + rootMessenger.call('RampsController:addOrder', orderWithoutProvider); const handler = jest.fn(); rootMessenger.registerActionHandler('RampsService:getOrder', handler); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(handler).not.toHaveBeenCalled(); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('skips orders without providerOrderId', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const orderNoId = createMockOrder({ providerOrderId: '', status: RampsOrderStatus.Pending, provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(orderNoId); + rootMessenger.call('RampsController:addOrder', orderNoId); const handler = jest.fn(); rootMessenger.registerActionHandler('RampsService:getOrder', handler); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(handler).not.toHaveBeenCalled(); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('skips orders without wallet address', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const orderNoWallet = createMockOrder({ providerOrderId: 'no-wallet-1', status: RampsOrderStatus.Pending, provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '', }); - controller.addOrder(orderNoWallet); + rootMessenger.call('RampsController:addOrder', orderNoWallet); const handler = jest.fn(); rootMessenger.registerActionHandler('RampsService:getOrder', handler); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(handler).not.toHaveBeenCalled(); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('strips /providers/ prefix from provider id', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const order = createMockOrder({ providerOrderId: 'strip-prefix-1', status: RampsOrderStatus.Pending, provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(order); + rootMessenger.call('RampsController:addOrder', order); const handler = jest.fn(async () => ({ ...order, @@ -5761,7 +6061,7 @@ describe('RampsController', () => { })); rootMessenger.registerActionHandler('RampsService:getOrder', handler); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(handler).toHaveBeenCalledWith( @@ -5770,19 +6070,19 @@ describe('RampsController', () => { '0xabc', ); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('skips polling orders that have not waited long enough (backoff)', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const order = createMockOrder({ providerOrderId: 'backoff-1', status: RampsOrderStatus.Pending, provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(order); + rootMessenger.call('RampsController:addOrder', order); let callCount = 0; rootMessenger.registerActionHandler( @@ -5793,19 +6093,19 @@ describe('RampsController', () => { }, ); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(callCount).toBe(1); await jest.advanceTimersByTimeAsync(30_000); expect(callCount).toBe(2); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('respects pollingSecondsMinimum on orders', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const order = createMockOrder({ providerOrderId: 'poll-min-1', status: RampsOrderStatus.Pending, @@ -5813,7 +6113,7 @@ describe('RampsController', () => { walletAddress: '0xabc', pollingSecondsMinimum: 120, }); - controller.addOrder(order); + rootMessenger.call('RampsController:addOrder', order); let callCount = 0; rootMessenger.registerActionHandler( @@ -5824,7 +6124,7 @@ describe('RampsController', () => { }, ); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(callCount).toBe(1); @@ -5834,30 +6134,30 @@ describe('RampsController', () => { await jest.advanceTimersByTimeAsync(90_000); expect(callCount).toBe(2); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('catches errors if poll cycle throws synchronously on initial call', async () => { - await withController(async ({ controller }) => { + await withController(async ({ controller, rootMessenger }) => { const realState = controller.state; jest.spyOn(controller, 'state', 'get').mockReturnValue({ ...realState, orders: null as unknown as RampsOrder[], }); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); jest.restoreAllMocks(); expect(controller.state.orders).toStrictEqual([]); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('catches errors if poll cycle throws on interval tick', async () => { - await withController(async ({ controller }) => { - controller.startOrderPolling(); + await withController(async ({ controller, rootMessenger }) => { + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); const realState = controller.state; @@ -5870,41 +6170,41 @@ describe('RampsController', () => { jest.restoreAllMocks(); expect(controller.state.orders).toStrictEqual([]); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('does not poll orders with terminal statuses', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const completedOrder = createMockOrder({ providerOrderId: 'completed-1', status: RampsOrderStatus.Completed, provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(completedOrder); + rootMessenger.call('RampsController:addOrder', completedOrder); const handler = jest.fn(); rootMessenger.registerActionHandler('RampsService:getOrder', handler); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(handler).not.toHaveBeenCalled(); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('resets error count when order returns non-Unknown status', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const order = createMockOrder({ providerOrderId: 'reset-err-1', status: RampsOrderStatus.Pending, provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(order); + rootMessenger.call('RampsController:addOrder', order); let callCount = 0; rootMessenger.registerActionHandler( @@ -5918,7 +6218,7 @@ describe('RampsController', () => { }, ); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); expect(callCount).toBe(1); @@ -5928,19 +6228,19 @@ describe('RampsController', () => { await jest.advanceTimersByTimeAsync(30_000); expect(callCount).toBe(3); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); it('does not run concurrent polls when stop+start is called while a poll is in-flight', async () => { - await withController(async ({ controller, rootMessenger, messenger }) => { + await withController(async ({ rootMessenger, messenger }) => { const pendingOrder = createMockOrder({ providerOrderId: 'race-1', status: RampsOrderStatus.Pending, provider: { id: '/providers/transak', name: 'Transak' }, walletAddress: '0xabc', }); - controller.addOrder(pendingOrder); + rootMessenger.call('RampsController:addOrder', pendingOrder); const updatedOrder = { ...pendingOrder, @@ -5969,11 +6269,11 @@ describe('RampsController', () => { statusChangedListener, ); - controller.startOrderPolling(); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); - controller.stopOrderPolling(); - controller.startOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); + rootMessenger.call('RampsController:startOrderPolling'); await jest.advanceTimersByTimeAsync(0); resolveFirst(updatedOrder); @@ -5981,7 +6281,7 @@ describe('RampsController', () => { expect(statusChangedListener).toHaveBeenCalledTimes(1); - controller.stopOrderPolling(); + rootMessenger.call('RampsController:stopOrderPolling'); }); }); }); @@ -5989,13 +6289,16 @@ describe('RampsController', () => { describe('Transak methods', () => { describe('transakSetApiKey', () => { it('calls messenger with the api key', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const handler = jest.fn(); rootMessenger.registerActionHandler( 'TransakService:setApiKey', handler, ); - controller.transakSetApiKey('test-api-key'); + rootMessenger.call( + 'RampsController:transakSetApiKey', + 'test-api-key', + ); expect(handler).toHaveBeenCalledWith('test-api-key'); }); }); @@ -6014,7 +6317,7 @@ describe('RampsController', () => { ttl: 3600, created: new Date('2024-01-01'), }; - controller.transakSetAccessToken(token); + rootMessenger.call('RampsController:transakSetAccessToken', token); expect(handler).toHaveBeenCalledWith(token); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( true, @@ -6034,7 +6337,7 @@ describe('RampsController', () => { 'TransakService:clearAccessToken', jest.fn(), ); - controller.transakSetAccessToken({ + rootMessenger.call('RampsController:transakSetAccessToken', { accessToken: 'tok', ttl: 3600, created: new Date('2024-01-01'), @@ -6042,7 +6345,7 @@ describe('RampsController', () => { expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( true, ); - controller.transakClearAccessToken(); + rootMessenger.call('RampsController:transakClearAccessToken'); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, ); @@ -6052,15 +6355,15 @@ describe('RampsController', () => { describe('transakSetAuthenticated', () => { it('sets isAuthenticated in transak state', async () => { - await withController(async ({ controller }) => { + await withController(async ({ controller, rootMessenger }) => { expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, ); - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( true, ); - controller.transakSetAuthenticated(false); + rootMessenger.call('RampsController:transakSetAuthenticated', false); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, ); @@ -6080,7 +6383,7 @@ describe('RampsController', () => { 'TransakService:clearAccessToken', clearAccessTokenHandler, ); - controller.transakSetAccessToken({ + rootMessenger.call('RampsController:transakSetAccessToken', { accessToken: 'tok', ttl: 3600, created: new Date('2024-01-01'), @@ -6089,7 +6392,7 @@ describe('RampsController', () => { true, ); - controller.transakResetState(); + rootMessenger.call('RampsController:transakResetState'); expect(clearAccessTokenHandler).toHaveBeenCalled(); expect(controller.state.nativeProviders.transak) @@ -6122,7 +6425,7 @@ describe('RampsController', () => { describe('transakSendUserOtp', () => { it('calls messenger with email and returns result', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const mockResult = { isTncAccepted: true, stateToken: 'state-token', @@ -6133,8 +6436,10 @@ describe('RampsController', () => { 'TransakService:sendUserOtp', async () => mockResult, ); - const result = - await controller.transakSendUserOtp('test@example.com'); + const result = await rootMessenger.call( + 'RampsController:transakSendUserOtp', + 'test@example.com', + ); expect(result).toStrictEqual(mockResult); }); }); @@ -6152,7 +6457,8 @@ describe('RampsController', () => { 'TransakService:verifyUserOtp', async () => mockToken, ); - const result = await controller.transakVerifyUserOtp( + const result = await rootMessenger.call( + 'RampsController:transakVerifyUserOtp', 'test@example.com', '123456', 'state-token', @@ -6181,7 +6487,7 @@ describe('RampsController', () => { 'TransakService:logout', async () => 'logged out', ); - controller.transakSetAccessToken({ + rootMessenger.call('RampsController:transakSetAccessToken', { accessToken: 'tok', ttl: 3600, created: new Date('2024-01-01'), @@ -6190,7 +6496,9 @@ describe('RampsController', () => { true, ); - const result = await controller.transakLogout(); + const result = await rootMessenger.call( + 'RampsController:transakLogout', + ); expect(result).toBe('logged out'); expect(clearAccessTokenHandler).toHaveBeenCalled(); @@ -6220,15 +6528,15 @@ describe('RampsController', () => { throw new Error('Network error'); }, ); - controller.transakSetAccessToken({ + rootMessenger.call('RampsController:transakSetAccessToken', { accessToken: 'tok', ttl: 3600, created: new Date('2024-01-01'), }); - await expect(controller.transakLogout()).rejects.toThrow( - 'Network error', - ); + await expect( + rootMessenger.call('RampsController:transakLogout'), + ).rejects.toThrow('Network error'); expect(clearAccessTokenHandler).toHaveBeenCalled(); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, @@ -6278,7 +6586,9 @@ describe('RampsController', () => { 'TransakService:getUserDetails', async () => mockUserDetails, ); - const result = await controller.transakGetUserDetails(); + const result = await rootMessenger.call( + 'RampsController:transakGetUserDetails', + ); expect(result).toStrictEqual(mockUserDetails); expect(controller.state.nativeProviders.transak.userDetails) .toMatchInlineSnapshot(` @@ -6329,9 +6639,9 @@ describe('RampsController', () => { throw new Error('Auth failed'); }, ); - await expect(controller.transakGetUserDetails()).rejects.toThrow( - 'Auth failed', - ); + await expect( + rootMessenger.call('RampsController:transakGetUserDetails'), + ).rejects.toThrow('Auth failed'); expect( controller.state.nativeProviders.transak.userDetails.isLoading, ).toBe(false); @@ -6350,7 +6660,9 @@ describe('RampsController', () => { throw null; }, ); - await expect(controller.transakGetUserDetails()).rejects.toBeNull(); + await expect( + rootMessenger.call('RampsController:transakGetUserDetails'), + ).rejects.toBeNull(); expect( controller.state.nativeProviders.transak.userDetails.error, ).toBe('Unknown error'); @@ -6359,7 +6671,7 @@ describe('RampsController', () => { it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:getUserDetails', async () => { @@ -6368,9 +6680,9 @@ describe('RampsController', () => { }); }, ); - await expect(controller.transakGetUserDetails()).rejects.toThrow( - 'Token expired', - ); + await expect( + rootMessenger.call('RampsController:transakGetUserDetails'), + ).rejects.toThrow('Token expired'); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, ); @@ -6379,7 +6691,7 @@ describe('RampsController', () => { it('does not change isAuthenticated for non-401 errors', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:getUserDetails', async () => { @@ -6388,9 +6700,9 @@ describe('RampsController', () => { }); }, ); - await expect(controller.transakGetUserDetails()).rejects.toThrow( - 'Server error', - ); + await expect( + rootMessenger.call('RampsController:transakGetUserDetails'), + ).rejects.toThrow('Server error'); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( true, ); @@ -6425,7 +6737,8 @@ describe('RampsController', () => { 'TransakService:getBuyQuote', async () => mockBuyQuote, ); - const result = await controller.transakGetBuyQuote( + const result = await rootMessenger.call( + 'RampsController:transakGetBuyQuote', 'USD', 'BTC', 'bitcoin', @@ -6472,7 +6785,8 @@ describe('RampsController', () => { }, ); await expect( - controller.transakGetBuyQuote( + rootMessenger.call( + 'RampsController:transakGetBuyQuote', 'USD', 'BTC', 'bitcoin', @@ -6499,7 +6813,8 @@ describe('RampsController', () => { }, ); await expect( - controller.transakGetBuyQuote( + rootMessenger.call( + 'RampsController:transakGetBuyQuote', 'USD', 'BTC', 'bitcoin', @@ -6585,7 +6900,7 @@ describe('RampsController', () => { it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:getKycRequirement', async () => { @@ -6622,7 +6937,7 @@ describe('RampsController', () => { it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:getAdditionalRequirements', async () => { @@ -6643,14 +6958,15 @@ describe('RampsController', () => { describe('transakCreateOrder', () => { it('calls messenger with correct arguments and returns result', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const mockOrder = createMockDepositOrder(); const handler = jest.fn().mockResolvedValue(mockOrder); rootMessenger.registerActionHandler( 'TransakService:createOrder', handler, ); - const result = await controller.transakCreateOrder( + const result = await rootMessenger.call( + 'RampsController:transakCreateOrder', 'quote-1', '0x123', '/payments/debit-credit-card', @@ -6666,7 +6982,7 @@ describe('RampsController', () => { it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:createOrder', async () => { @@ -6676,7 +6992,12 @@ describe('RampsController', () => { }, ); await expect( - controller.transakCreateOrder('quote-1', '0x123', 'card'), + rootMessenger.call( + 'RampsController:transakCreateOrder', + 'quote-1', + '0x123', + 'card', + ), ).rejects.toThrow('Token expired'); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, @@ -6687,19 +7008,23 @@ describe('RampsController', () => { describe('transakGetOrder', () => { it('calls messenger with orderId and wallet', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const mockOrder = createMockDepositOrder(); rootMessenger.registerActionHandler( 'TransakService:getOrder', async () => mockOrder, ); - const result = await controller.transakGetOrder('order-1', '0x123'); + const result = await rootMessenger.call( + 'RampsController:transakGetOrder', + 'order-1', + '0x123', + ); expect(result).toStrictEqual(mockOrder); }); }); it('passes optional paymentDetails to messenger', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const mockOrder = createMockDepositOrder(); const paymentDetails: TransakOrderPaymentMethod[] = [ { @@ -6713,7 +7038,12 @@ describe('RampsController', () => { 'TransakService:getOrder', handler, ); - await controller.transakGetOrder('order-1', '0x123', paymentDetails); + await rootMessenger.call( + 'RampsController:transakGetOrder', + 'order-1', + '0x123', + paymentDetails, + ); expect(handler).toHaveBeenCalledWith( 'order-1', '0x123', @@ -6748,7 +7078,7 @@ describe('RampsController', () => { it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:getUserLimits', async () => { @@ -6769,20 +7099,22 @@ describe('RampsController', () => { describe('transakRequestOtt', () => { it('calls messenger and returns result', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const mockResult: TransakOttResponse = { ott: 'ott-token-123' }; rootMessenger.registerActionHandler( 'TransakService:requestOtt', async () => mockResult, ); - const result = await controller.transakRequestOtt(); + const result = await rootMessenger.call( + 'RampsController:transakRequestOtt', + ); expect(result).toStrictEqual(mockResult); }); }); it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:requestOtt', async () => { @@ -6791,9 +7123,9 @@ describe('RampsController', () => { }); }, ); - await expect(controller.transakRequestOtt()).rejects.toThrow( - 'Token expired', - ); + await expect( + rootMessenger.call('RampsController:transakRequestOtt'), + ).rejects.toThrow('Token expired'); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, ); @@ -6823,12 +7155,13 @@ describe('RampsController', () => { }; it('calls messenger with correct arguments and returns URL', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { rootMessenger.registerActionHandler( 'TransakService:generatePaymentWidgetUrl', () => 'https://widget.transak.com?param=value', ); - const result = controller.transakGeneratePaymentWidgetUrl( + const result = rootMessenger.call( + 'RampsController:transakGeneratePaymentWidgetUrl', 'ott-token', mockQuote, '0x123', @@ -6838,7 +7171,7 @@ describe('RampsController', () => { }); it('passes optional extraParams to messenger', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const handler = jest .fn() .mockReturnValue('https://widget.transak.com'); @@ -6847,7 +7180,8 @@ describe('RampsController', () => { handler, ); const extraParams = { themeColor: 'blue' }; - controller.transakGeneratePaymentWidgetUrl( + rootMessenger.call( + 'RampsController:transakGeneratePaymentWidgetUrl', 'ott-token', mockQuote, '0x123', @@ -6865,23 +7199,23 @@ describe('RampsController', () => { describe('transakSubmitPurposeOfUsageForm', () => { it('calls messenger with purpose array', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const handler = jest.fn().mockResolvedValue(undefined); rootMessenger.registerActionHandler( 'TransakService:submitPurposeOfUsageForm', handler, ); - await controller.transakSubmitPurposeOfUsageForm([ - 'investment', - 'trading', - ]); + await rootMessenger.call( + 'RampsController:transakSubmitPurposeOfUsageForm', + ['investment', 'trading'], + ); expect(handler).toHaveBeenCalledWith(['investment', 'trading']); }); }); it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:submitPurposeOfUsageForm', async () => { @@ -6891,7 +7225,10 @@ describe('RampsController', () => { }, ); await expect( - controller.transakSubmitPurposeOfUsageForm(['investment']), + rootMessenger.call( + 'RampsController:transakSubmitPurposeOfUsageForm', + ['investment'], + ), ).rejects.toThrow('Token expired'); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, @@ -6902,7 +7239,7 @@ describe('RampsController', () => { describe('transakPatchUser', () => { it('calls messenger with user data and returns result', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const data: PatchUserRequestBody = { personalDetails: { firstName: 'Jane', lastName: 'Doe' }, }; @@ -6911,7 +7248,10 @@ describe('RampsController', () => { 'TransakService:patchUser', handler, ); - const result = await controller.transakPatchUser(data); + const result = await rootMessenger.call( + 'RampsController:transakPatchUser', + data, + ); expect(handler).toHaveBeenCalledWith(data); expect(result).toStrictEqual({ success: true }); }); @@ -6919,7 +7259,7 @@ describe('RampsController', () => { it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:patchUser', async () => { @@ -6929,7 +7269,7 @@ describe('RampsController', () => { }, ); await expect( - controller.transakPatchUser({ + rootMessenger.call('RampsController:transakPatchUser', { personalDetails: { firstName: 'Jane' }, }), ).rejects.toThrow('Token expired'); @@ -6942,13 +7282,14 @@ describe('RampsController', () => { describe('transakSubmitSsnDetails', () => { it('calls messenger with ssn and quoteId', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const handler = jest.fn().mockResolvedValue({ success: true }); rootMessenger.registerActionHandler( 'TransakService:submitSsnDetails', handler, ); - const result = await controller.transakSubmitSsnDetails( + const result = await rootMessenger.call( + 'RampsController:transakSubmitSsnDetails', '123-45-6789', 'quote-1', ); @@ -6959,7 +7300,7 @@ describe('RampsController', () => { it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:submitSsnDetails', async () => { @@ -6969,7 +7310,11 @@ describe('RampsController', () => { }, ); await expect( - controller.transakSubmitSsnDetails('123-45-6789', 'quote-1'), + rootMessenger.call( + 'RampsController:transakSubmitSsnDetails', + '123-45-6789', + 'quote-1', + ), ).rejects.toThrow('Token expired'); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, @@ -6980,13 +7325,14 @@ describe('RampsController', () => { describe('transakConfirmPayment', () => { it('calls messenger with orderId and paymentMethodId', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const handler = jest.fn().mockResolvedValue({ success: true }); rootMessenger.registerActionHandler( 'TransakService:confirmPayment', handler, ); - const result = await controller.transakConfirmPayment( + const result = await rootMessenger.call( + 'RampsController:transakConfirmPayment', 'order-1', '/payments/debit-credit-card', ); @@ -7000,7 +7346,7 @@ describe('RampsController', () => { it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:confirmPayment', async () => { @@ -7010,7 +7356,11 @@ describe('RampsController', () => { }, ); await expect( - controller.transakConfirmPayment('order-1', 'card'), + rootMessenger.call( + 'RampsController:transakConfirmPayment', + 'order-1', + 'card', + ), ).rejects.toThrow('Token expired'); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, @@ -7021,7 +7371,7 @@ describe('RampsController', () => { describe('transakGetTranslation', () => { it('calls messenger with translation request and returns result', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const mockTranslation: TransakQuoteTranslation = { region: 'US', paymentMethod: 'credit_debit_card', @@ -7039,7 +7389,10 @@ describe('RampsController', () => { 'TransakService:getTranslation', async () => mockTranslation, ); - const result = await controller.transakGetTranslation(request); + const result = await rootMessenger.call( + 'RampsController:transakGetTranslation', + request, + ); expect(result).toStrictEqual(mockTranslation); }); }); @@ -7064,7 +7417,7 @@ describe('RampsController', () => { it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:getIdProofStatus', async () => { @@ -7085,13 +7438,14 @@ describe('RampsController', () => { describe('transakCancelOrder', () => { it('calls messenger with depositOrderId', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const handler = jest.fn().mockResolvedValue(undefined); rootMessenger.registerActionHandler( 'TransakService:cancelOrder', handler, ); - await controller.transakCancelOrder( + await rootMessenger.call( + 'RampsController:transakCancelOrder', '/providers/transak-native/orders/order-1', ); expect(handler).toHaveBeenCalledWith( @@ -7102,7 +7456,7 @@ describe('RampsController', () => { it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:cancelOrder', async () => { @@ -7112,7 +7466,7 @@ describe('RampsController', () => { }, ); await expect( - controller.transakCancelOrder('order-1'), + rootMessenger.call('RampsController:transakCancelOrder', 'order-1'), ).rejects.toThrow('Token expired'); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, @@ -7123,13 +7477,15 @@ describe('RampsController', () => { describe('transakCancelAllActiveOrders', () => { it('calls messenger and returns collected errors', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const handler = jest.fn().mockResolvedValue([]); rootMessenger.registerActionHandler( 'TransakService:cancelAllActiveOrders', handler, ); - const errors = await controller.transakCancelAllActiveOrders(); + const errors = await rootMessenger.call( + 'RampsController:transakCancelAllActiveOrders', + ); expect(handler).toHaveBeenCalled(); expect(errors).toStrictEqual([]); }); @@ -7137,7 +7493,7 @@ describe('RampsController', () => { it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:cancelAllActiveOrders', async () => { @@ -7147,7 +7503,7 @@ describe('RampsController', () => { }, ); await expect( - controller.transakCancelAllActiveOrders(), + rootMessenger.call('RampsController:transakCancelAllActiveOrders'), ).rejects.toThrow('Token expired'); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, @@ -7158,7 +7514,7 @@ describe('RampsController', () => { describe('transakGetActiveOrders', () => { it('calls messenger and returns orders', async () => { - await withController(async ({ controller, rootMessenger }) => { + await withController(async ({ rootMessenger }) => { const mockOrders: TransakOrder[] = [ { orderId: 'order-1', @@ -7188,14 +7544,16 @@ describe('RampsController', () => { 'TransakService:getActiveOrders', async () => mockOrders, ); - const result = await controller.transakGetActiveOrders(); + const result = await rootMessenger.call( + 'RampsController:transakGetActiveOrders', + ); expect(result).toStrictEqual(mockOrders); }); }); it('sets isAuthenticated to false when a 401 HttpError is thrown', async () => { await withController(async ({ controller, rootMessenger }) => { - controller.transakSetAuthenticated(true); + rootMessenger.call('RampsController:transakSetAuthenticated', true); rootMessenger.registerActionHandler( 'TransakService:getActiveOrders', async () => { @@ -7204,9 +7562,9 @@ describe('RampsController', () => { }); }, ); - await expect(controller.transakGetActiveOrders()).rejects.toThrow( - 'Token expired', - ); + await expect( + rootMessenger.call('RampsController:transakGetActiveOrders'), + ).rejects.toThrow('Token expired'); expect(controller.state.nativeProviders.transak.isAuthenticated).toBe( false, ); diff --git a/packages/ramps-controller/src/RampsController.ts b/packages/ramps-controller/src/RampsController.ts index 6f9e1b4a6ff..b7780295b81 100644 --- a/packages/ramps-controller/src/RampsController.ts +++ b/packages/ramps-controller/src/RampsController.ts @@ -8,6 +8,7 @@ import type { Messenger } from '@metamask/messenger'; import type { Json } from '@metamask/utils'; import type { Draft } from 'immer'; +import type { RampsControllerMethodActions } from './RampsController-method-action-types'; import type { BuyWidget, Country, @@ -435,38 +436,12 @@ export type RampsControllerGetStateAction = ControllerGetStateAction< RampsControllerState >; -/** - * Sets selected token in the {@link RampsController}. - */ -export type RampsControllerSetSelectedTokenAction = { - type: 'RampsController:setSelectedToken'; - handler: RampsController['setSelectedToken']; -}; - -/** - * Fetches quotes via the {@link RampsController}. - */ -export type RampsControllerGetQuotesAction = { - type: 'RampsController:getQuotes'; - handler: RampsController['getQuotes']; -}; - -/** - * Fetches an order via the {@link RampsController}. - */ -export type RampsControllerGetOrderAction = { - type: 'RampsController:getOrder'; - handler: RampsController['getOrder']; -}; - /** * Actions that {@link RampsControllerMessenger} exposes to other consumers. */ export type RampsControllerActions = | RampsControllerGetStateAction - | RampsControllerGetOrderAction - | RampsControllerGetQuotesAction - | RampsControllerSetSelectedTokenAction; + | RampsControllerMethodActions; /** * Actions from other messengers that {@link RampsController} calls. @@ -653,6 +628,56 @@ type OrderPollingMetadata = { // === CONTROLLER DEFINITION === +const MESSENGER_EXPOSED_METHODS = [ + 'executeRequest', + 'abortRequest', + 'getRequestState', + 'setUserRegion', + 'setSelectedProvider', + 'init', + 'getCountries', + 'getTokens', + 'setSelectedToken', + 'getProviders', + 'getPaymentMethods', + 'setSelectedPaymentMethod', + 'getQuotes', + 'addOrder', + 'removeOrder', + 'startOrderPolling', + 'stopOrderPolling', + 'getBuyWidgetData', + 'addPrecreatedOrder', + 'getOrder', + 'getOrderFromCallback', + 'transakSetApiKey', + 'transakSetAccessToken', + 'transakClearAccessToken', + 'transakSetAuthenticated', + 'transakResetState', + 'transakSendUserOtp', + 'transakVerifyUserOtp', + 'transakLogout', + 'transakGetUserDetails', + 'transakGetBuyQuote', + 'transakGetKycRequirement', + 'transakGetAdditionalRequirements', + 'transakCreateOrder', + 'transakGetOrder', + 'transakGetUserLimits', + 'transakRequestOtt', + 'transakGeneratePaymentWidgetUrl', + 'transakSubmitPurposeOfUsageForm', + 'transakPatchUser', + 'transakSubmitSsnDetails', + 'transakConfirmPayment', + 'transakGetTranslation', + 'transakGetIdProofStatus', + 'transakCancelOrder', + 'transakCancelAllActiveOrders', + 'transakGetActiveOrders', +] as const; + /** * Manages cryptocurrency on/off ramps functionality. */ @@ -751,21 +776,9 @@ export class RampsController extends BaseController< this.#requestCacheTTL = requestCacheTTL; this.#requestCacheMaxSize = requestCacheMaxSize; - this.#registerActionHandlers(); - } - - #registerActionHandlers(): void { - this.messenger.registerActionHandler( - 'RampsController:getOrder', - this.getOrder.bind(this), - ); - this.messenger.registerActionHandler( - 'RampsController:getQuotes', - this.getQuotes.bind(this), - ); - this.messenger.registerActionHandler( - 'RampsController:setSelectedToken', - this.setSelectedToken.bind(this), + this.messenger.registerMethodActionHandlers( + this, + MESSENGER_EXPOSED_METHODS, ); } diff --git a/packages/ramps-controller/src/index.ts b/packages/ramps-controller/src/index.ts index 251ff917a1b..bb6a05edbf3 100644 --- a/packages/ramps-controller/src/index.ts +++ b/packages/ramps-controller/src/index.ts @@ -2,9 +2,6 @@ export type { RampsControllerActions, RampsControllerEvents, RampsControllerGetStateAction, - RampsControllerSetSelectedTokenAction, - RampsControllerGetQuotesAction, - RampsControllerGetOrderAction, RampsControllerMessenger, RampsControllerState, RampsControllerStateChangeEvent, @@ -15,6 +12,55 @@ export type { TransakState, NativeProvidersState, } from './RampsController'; +export type { + RampsControllerExecuteRequestAction, + RampsControllerAbortRequestAction, + RampsControllerGetRequestStateAction, + RampsControllerSetUserRegionAction, + RampsControllerSetSelectedProviderAction, + RampsControllerInitAction, + RampsControllerGetCountriesAction, + RampsControllerGetTokensAction, + RampsControllerSetSelectedTokenAction, + RampsControllerGetProvidersAction, + RampsControllerGetPaymentMethodsAction, + RampsControllerSetSelectedPaymentMethodAction, + RampsControllerGetQuotesAction, + RampsControllerAddOrderAction, + RampsControllerRemoveOrderAction, + RampsControllerStartOrderPollingAction, + RampsControllerStopOrderPollingAction, + RampsControllerGetBuyWidgetDataAction, + RampsControllerAddPrecreatedOrderAction, + RampsControllerGetOrderAction, + RampsControllerGetOrderFromCallbackAction, + RampsControllerTransakSetApiKeyAction, + RampsControllerTransakSetAccessTokenAction, + RampsControllerTransakClearAccessTokenAction, + RampsControllerTransakSetAuthenticatedAction, + RampsControllerTransakResetStateAction, + RampsControllerTransakSendUserOtpAction, + RampsControllerTransakVerifyUserOtpAction, + RampsControllerTransakLogoutAction, + RampsControllerTransakGetUserDetailsAction, + RampsControllerTransakGetBuyQuoteAction, + RampsControllerTransakGetKycRequirementAction, + RampsControllerTransakGetAdditionalRequirementsAction, + RampsControllerTransakCreateOrderAction, + RampsControllerTransakGetOrderAction, + RampsControllerTransakGetUserLimitsAction, + RampsControllerTransakRequestOttAction, + RampsControllerTransakGeneratePaymentWidgetUrlAction, + RampsControllerTransakSubmitPurposeOfUsageFormAction, + RampsControllerTransakPatchUserAction, + RampsControllerTransakSubmitSsnDetailsAction, + RampsControllerTransakConfirmPaymentAction, + RampsControllerTransakGetTranslationAction, + RampsControllerTransakGetIdProofStatusAction, + RampsControllerTransakCancelOrderAction, + RampsControllerTransakCancelAllActiveOrdersAction, + RampsControllerTransakGetActiveOrdersAction, +} from './RampsController-method-action-types'; export { RampsController, getDefaultRampsControllerState,