@metamask/ramps-controller 1.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -1
- package/dist/RampsController.cjs +226 -6
- package/dist/RampsController.cjs.map +1 -1
- package/dist/RampsController.d.cts +80 -10
- package/dist/RampsController.d.cts.map +1 -1
- package/dist/RampsController.d.mts +80 -10
- package/dist/RampsController.d.mts.map +1 -1
- package/dist/RampsController.mjs +226 -6
- package/dist/RampsController.mjs.map +1 -1
- package/dist/{OnRampService-method-action-types.cjs → RampsService-method-action-types.cjs} +1 -1
- package/dist/RampsService-method-action-types.cjs.map +1 -0
- package/dist/RampsService-method-action-types.d.cts +41 -0
- package/dist/RampsService-method-action-types.d.cts.map +1 -0
- package/dist/RampsService-method-action-types.d.mts +41 -0
- package/dist/RampsService-method-action-types.d.mts.map +1 -0
- package/dist/{OnRampService-method-action-types.mjs → RampsService-method-action-types.mjs} +1 -1
- package/dist/RampsService-method-action-types.mjs.map +1 -0
- package/dist/RampsService.cjs +288 -0
- package/dist/RampsService.cjs.map +1 -0
- package/dist/RampsService.d.cts +275 -0
- package/dist/RampsService.d.cts.map +1 -0
- package/dist/RampsService.d.mts +275 -0
- package/dist/RampsService.d.mts.map +1 -0
- package/dist/RampsService.mjs +281 -0
- package/dist/RampsService.mjs.map +1 -0
- package/dist/RequestCache.cjs +98 -0
- package/dist/RequestCache.cjs.map +1 -0
- package/dist/RequestCache.d.cts +93 -0
- package/dist/RequestCache.d.cts.map +1 -0
- package/dist/RequestCache.d.mts +93 -0
- package/dist/RequestCache.d.mts.map +1 -0
- package/dist/RequestCache.mjs +90 -0
- package/dist/RequestCache.mjs.map +1 -0
- package/dist/index.cjs +17 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +8 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -1
- package/dist/index.mjs.map +1 -1
- package/dist/selectors.cjs +81 -0
- package/dist/selectors.cjs.map +1 -0
- package/dist/selectors.d.cts +75 -0
- package/dist/selectors.d.cts.map +1 -0
- package/dist/selectors.d.mts +75 -0
- package/dist/selectors.d.mts.map +1 -0
- package/dist/selectors.mjs +77 -0
- package/dist/selectors.mjs.map +1 -0
- package/package.json +3 -2
- package/dist/OnRampService-method-action-types.cjs.map +0 -1
- package/dist/OnRampService-method-action-types.d.cts +0 -20
- package/dist/OnRampService-method-action-types.d.cts.map +0 -1
- package/dist/OnRampService-method-action-types.d.mts +0 -20
- package/dist/OnRampService-method-action-types.d.mts.map +0 -1
- package/dist/OnRampService-method-action-types.mjs.map +0 -1
- package/dist/OnRampService.cjs +0 -204
- package/dist/OnRampService.cjs.map +0 -1
- package/dist/OnRampService.d.cts +0 -152
- package/dist/OnRampService.d.cts.map +0 -1
- package/dist/OnRampService.d.mts +0 -152
- package/dist/OnRampService.d.mts.map +0 -1
- package/dist/OnRampService.mjs +0 -200
- package/dist/OnRampService.mjs.map +0 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { RampsControllerState } from "./RampsController.cjs";
|
|
2
|
+
/**
|
|
3
|
+
* Result shape returned by request selectors.
|
|
4
|
+
*
|
|
5
|
+
* This object is memoized - the same reference is returned when the underlying
|
|
6
|
+
* request state hasn't changed, making it safe to use with React Redux's
|
|
7
|
+
* `useSelector` without `shallowEqual`.
|
|
8
|
+
*/
|
|
9
|
+
export type RequestSelectorResult<TData> = {
|
|
10
|
+
/** The data returned by the request, or null if not yet loaded or on error. */
|
|
11
|
+
data: TData | null;
|
|
12
|
+
/** Whether the request is currently in progress. */
|
|
13
|
+
isFetching: boolean;
|
|
14
|
+
/** Error message if the request failed, or null if successful or not yet attempted. */
|
|
15
|
+
error: string | null;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Creates a memoized selector for a controller method's request state.
|
|
19
|
+
*
|
|
20
|
+
* This selector tracks the loading, error, and data state for a specific
|
|
21
|
+
* controller method call. It's optimized for use with React Redux's `useSelector`
|
|
22
|
+
* hook - the selector returns the same object reference when the underlying
|
|
23
|
+
* request state hasn't changed, so no `shallowEqual` is needed.
|
|
24
|
+
*
|
|
25
|
+
* The selector uses reference equality on the request object itself, so it
|
|
26
|
+
* works correctly with arrays and objects without expensive deep equality checks.
|
|
27
|
+
*
|
|
28
|
+
* @param getState - Function that extracts RampsControllerState from the root state.
|
|
29
|
+
* Typically a reselect selector like `selectRampsControllerState`.
|
|
30
|
+
* @param method - The controller method name (e.g., 'updateGeolocation').
|
|
31
|
+
* @param params - The parameters passed to the method, used to generate the cache key.
|
|
32
|
+
* Must match the params used when calling the controller method.
|
|
33
|
+
* @returns A selector function that returns `{ data, isFetching, error }`.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* // In selectors file - create once at module level
|
|
38
|
+
* import { createRequestSelector } from '@metamask/ramps-controller';
|
|
39
|
+
* import { createSelector } from 'reselect';
|
|
40
|
+
*
|
|
41
|
+
* const selectRampsControllerState = createSelector(
|
|
42
|
+
* (state: RootState) => state.engine.backgroundState.RampsController,
|
|
43
|
+
* (rampsControllerState) => rampsControllerState,
|
|
44
|
+
* );
|
|
45
|
+
*
|
|
46
|
+
* export const selectGeolocationRequest = createRequestSelector<
|
|
47
|
+
* RootState,
|
|
48
|
+
* string
|
|
49
|
+
* >(selectRampsControllerState, 'updateGeolocation', []);
|
|
50
|
+
*
|
|
51
|
+
* // In hook - use directly with useSelector, no shallowEqual needed
|
|
52
|
+
* export function useRampsGeolocation() {
|
|
53
|
+
* const { isFetching, error } = useSelector(selectGeolocationRequest);
|
|
54
|
+
* // ... rest of hook
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* // For methods with parameters
|
|
61
|
+
* export const selectCryptoCurrenciesRequest = (region: string) =>
|
|
62
|
+
* createRequestSelector<RootState, CryptoCurrency[]>(
|
|
63
|
+
* selectRampsControllerState,
|
|
64
|
+
* 'getCryptoCurrencies',
|
|
65
|
+
* [region],
|
|
66
|
+
* );
|
|
67
|
+
*
|
|
68
|
+
* // In component
|
|
69
|
+
* const { data, isFetching, error } = useSelector(
|
|
70
|
+
* selectCryptoCurrenciesRequest('US')
|
|
71
|
+
* );
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare function createRequestSelector<TRootState, TData>(getState: (rootState: TRootState) => RampsControllerState | undefined, method: string, params: unknown[]): (state: TRootState) => RequestSelectorResult<TData>;
|
|
75
|
+
//# sourceMappingURL=selectors.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.d.cts","sourceRoot":"","sources":["../src/selectors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,8BAA0B;AAI9D;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,CAAC,KAAK,IAAI;IACzC,+EAA+E;IAC/E,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IACnB,oDAAoD;IACpD,UAAU,EAAE,OAAO,CAAC;IACpB,uFAAuF;IACvF,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,KAAK,EACrD,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,KAAK,oBAAoB,GAAG,SAAS,EACrE,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EAAE,GAChB,CAAC,KAAK,EAAE,UAAU,KAAK,qBAAqB,CAAC,KAAK,CAAC,CAsBrD"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { RampsControllerState } from "./RampsController.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Result shape returned by request selectors.
|
|
4
|
+
*
|
|
5
|
+
* This object is memoized - the same reference is returned when the underlying
|
|
6
|
+
* request state hasn't changed, making it safe to use with React Redux's
|
|
7
|
+
* `useSelector` without `shallowEqual`.
|
|
8
|
+
*/
|
|
9
|
+
export type RequestSelectorResult<TData> = {
|
|
10
|
+
/** The data returned by the request, or null if not yet loaded or on error. */
|
|
11
|
+
data: TData | null;
|
|
12
|
+
/** Whether the request is currently in progress. */
|
|
13
|
+
isFetching: boolean;
|
|
14
|
+
/** Error message if the request failed, or null if successful or not yet attempted. */
|
|
15
|
+
error: string | null;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Creates a memoized selector for a controller method's request state.
|
|
19
|
+
*
|
|
20
|
+
* This selector tracks the loading, error, and data state for a specific
|
|
21
|
+
* controller method call. It's optimized for use with React Redux's `useSelector`
|
|
22
|
+
* hook - the selector returns the same object reference when the underlying
|
|
23
|
+
* request state hasn't changed, so no `shallowEqual` is needed.
|
|
24
|
+
*
|
|
25
|
+
* The selector uses reference equality on the request object itself, so it
|
|
26
|
+
* works correctly with arrays and objects without expensive deep equality checks.
|
|
27
|
+
*
|
|
28
|
+
* @param getState - Function that extracts RampsControllerState from the root state.
|
|
29
|
+
* Typically a reselect selector like `selectRampsControllerState`.
|
|
30
|
+
* @param method - The controller method name (e.g., 'updateGeolocation').
|
|
31
|
+
* @param params - The parameters passed to the method, used to generate the cache key.
|
|
32
|
+
* Must match the params used when calling the controller method.
|
|
33
|
+
* @returns A selector function that returns `{ data, isFetching, error }`.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* // In selectors file - create once at module level
|
|
38
|
+
* import { createRequestSelector } from '@metamask/ramps-controller';
|
|
39
|
+
* import { createSelector } from 'reselect';
|
|
40
|
+
*
|
|
41
|
+
* const selectRampsControllerState = createSelector(
|
|
42
|
+
* (state: RootState) => state.engine.backgroundState.RampsController,
|
|
43
|
+
* (rampsControllerState) => rampsControllerState,
|
|
44
|
+
* );
|
|
45
|
+
*
|
|
46
|
+
* export const selectGeolocationRequest = createRequestSelector<
|
|
47
|
+
* RootState,
|
|
48
|
+
* string
|
|
49
|
+
* >(selectRampsControllerState, 'updateGeolocation', []);
|
|
50
|
+
*
|
|
51
|
+
* // In hook - use directly with useSelector, no shallowEqual needed
|
|
52
|
+
* export function useRampsGeolocation() {
|
|
53
|
+
* const { isFetching, error } = useSelector(selectGeolocationRequest);
|
|
54
|
+
* // ... rest of hook
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* // For methods with parameters
|
|
61
|
+
* export const selectCryptoCurrenciesRequest = (region: string) =>
|
|
62
|
+
* createRequestSelector<RootState, CryptoCurrency[]>(
|
|
63
|
+
* selectRampsControllerState,
|
|
64
|
+
* 'getCryptoCurrencies',
|
|
65
|
+
* [region],
|
|
66
|
+
* );
|
|
67
|
+
*
|
|
68
|
+
* // In component
|
|
69
|
+
* const { data, isFetching, error } = useSelector(
|
|
70
|
+
* selectCryptoCurrenciesRequest('US')
|
|
71
|
+
* );
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare function createRequestSelector<TRootState, TData>(getState: (rootState: TRootState) => RampsControllerState | undefined, method: string, params: unknown[]): (state: TRootState) => RequestSelectorResult<TData>;
|
|
75
|
+
//# sourceMappingURL=selectors.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.d.mts","sourceRoot":"","sources":["../src/selectors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,8BAA0B;AAI9D;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,CAAC,KAAK,IAAI;IACzC,+EAA+E;IAC/E,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IACnB,oDAAoD;IACpD,UAAU,EAAE,OAAO,CAAC;IACpB,uFAAuF;IACvF,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,KAAK,EACrD,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,KAAK,oBAAoB,GAAG,SAAS,EACrE,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EAAE,GAChB,CAAC,KAAK,EAAE,UAAU,KAAK,qBAAqB,CAAC,KAAK,CAAC,CAsBrD"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { RequestStatus, createCacheKey } from "./RequestCache.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a memoized selector for a controller method's request state.
|
|
4
|
+
*
|
|
5
|
+
* This selector tracks the loading, error, and data state for a specific
|
|
6
|
+
* controller method call. It's optimized for use with React Redux's `useSelector`
|
|
7
|
+
* hook - the selector returns the same object reference when the underlying
|
|
8
|
+
* request state hasn't changed, so no `shallowEqual` is needed.
|
|
9
|
+
*
|
|
10
|
+
* The selector uses reference equality on the request object itself, so it
|
|
11
|
+
* works correctly with arrays and objects without expensive deep equality checks.
|
|
12
|
+
*
|
|
13
|
+
* @param getState - Function that extracts RampsControllerState from the root state.
|
|
14
|
+
* Typically a reselect selector like `selectRampsControllerState`.
|
|
15
|
+
* @param method - The controller method name (e.g., 'updateGeolocation').
|
|
16
|
+
* @param params - The parameters passed to the method, used to generate the cache key.
|
|
17
|
+
* Must match the params used when calling the controller method.
|
|
18
|
+
* @returns A selector function that returns `{ data, isFetching, error }`.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* // In selectors file - create once at module level
|
|
23
|
+
* import { createRequestSelector } from '@metamask/ramps-controller';
|
|
24
|
+
* import { createSelector } from 'reselect';
|
|
25
|
+
*
|
|
26
|
+
* const selectRampsControllerState = createSelector(
|
|
27
|
+
* (state: RootState) => state.engine.backgroundState.RampsController,
|
|
28
|
+
* (rampsControllerState) => rampsControllerState,
|
|
29
|
+
* );
|
|
30
|
+
*
|
|
31
|
+
* export const selectGeolocationRequest = createRequestSelector<
|
|
32
|
+
* RootState,
|
|
33
|
+
* string
|
|
34
|
+
* >(selectRampsControllerState, 'updateGeolocation', []);
|
|
35
|
+
*
|
|
36
|
+
* // In hook - use directly with useSelector, no shallowEqual needed
|
|
37
|
+
* export function useRampsGeolocation() {
|
|
38
|
+
* const { isFetching, error } = useSelector(selectGeolocationRequest);
|
|
39
|
+
* // ... rest of hook
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* // For methods with parameters
|
|
46
|
+
* export const selectCryptoCurrenciesRequest = (region: string) =>
|
|
47
|
+
* createRequestSelector<RootState, CryptoCurrency[]>(
|
|
48
|
+
* selectRampsControllerState,
|
|
49
|
+
* 'getCryptoCurrencies',
|
|
50
|
+
* [region],
|
|
51
|
+
* );
|
|
52
|
+
*
|
|
53
|
+
* // In component
|
|
54
|
+
* const { data, isFetching, error } = useSelector(
|
|
55
|
+
* selectCryptoCurrenciesRequest('US')
|
|
56
|
+
* );
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export function createRequestSelector(getState, method, params) {
|
|
60
|
+
const cacheKey = createCacheKey(method, params);
|
|
61
|
+
let lastRequest;
|
|
62
|
+
let lastResult = null;
|
|
63
|
+
return (state) => {
|
|
64
|
+
const request = getState(state)?.requests?.[cacheKey];
|
|
65
|
+
if (request === lastRequest && lastResult !== null) {
|
|
66
|
+
return lastResult;
|
|
67
|
+
}
|
|
68
|
+
lastRequest = request;
|
|
69
|
+
lastResult = {
|
|
70
|
+
data: request?.data ?? null,
|
|
71
|
+
isFetching: request?.status === RequestStatus.LOADING,
|
|
72
|
+
error: request?.error ?? null,
|
|
73
|
+
};
|
|
74
|
+
return lastResult;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=selectors.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.mjs","sourceRoot":"","sources":["../src/selectors.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,2BAAuB;AAkB/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAqE,EACrE,MAAc,EACd,MAAiB;IAEjB,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhD,IAAI,WAAqC,CAAC;IAC1C,IAAI,UAAU,GAAwC,IAAI,CAAC;IAE3D,OAAO,CAAC,KAAiB,EAAgC,EAAE;QACzD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC;QAEtD,IAAI,OAAO,KAAK,WAAW,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACnD,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,WAAW,GAAG,OAAO,CAAC;QACtB,UAAU,GAAG;YACX,IAAI,EAAG,OAAO,EAAE,IAAc,IAAI,IAAI;YACtC,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,aAAa,CAAC,OAAO;YACrD,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI;SAC9B,CAAC;QAEF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import type { RampsControllerState } from './RampsController';\nimport type { RequestState } from './RequestCache';\nimport { RequestStatus, createCacheKey } from './RequestCache';\n\n/**\n * Result shape returned by request selectors.\n *\n * This object is memoized - the same reference is returned when the underlying\n * request state hasn't changed, making it safe to use with React Redux's\n * `useSelector` without `shallowEqual`.\n */\nexport type RequestSelectorResult<TData> = {\n /** The data returned by the request, or null if not yet loaded or on error. */\n data: TData | null;\n /** Whether the request is currently in progress. */\n isFetching: boolean;\n /** Error message if the request failed, or null if successful or not yet attempted. */\n error: string | null;\n};\n\n/**\n * Creates a memoized selector for a controller method's request state.\n *\n * This selector tracks the loading, error, and data state for a specific\n * controller method call. It's optimized for use with React Redux's `useSelector`\n * hook - the selector returns the same object reference when the underlying\n * request state hasn't changed, so no `shallowEqual` is needed.\n *\n * The selector uses reference equality on the request object itself, so it\n * works correctly with arrays and objects without expensive deep equality checks.\n *\n * @param getState - Function that extracts RampsControllerState from the root state.\n * Typically a reselect selector like `selectRampsControllerState`.\n * @param method - The controller method name (e.g., 'updateGeolocation').\n * @param params - The parameters passed to the method, used to generate the cache key.\n * Must match the params used when calling the controller method.\n * @returns A selector function that returns `{ data, isFetching, error }`.\n *\n * @example\n * ```ts\n * // In selectors file - create once at module level\n * import { createRequestSelector } from '@metamask/ramps-controller';\n * import { createSelector } from 'reselect';\n *\n * const selectRampsControllerState = createSelector(\n * (state: RootState) => state.engine.backgroundState.RampsController,\n * (rampsControllerState) => rampsControllerState,\n * );\n *\n * export const selectGeolocationRequest = createRequestSelector<\n * RootState,\n * string\n * >(selectRampsControllerState, 'updateGeolocation', []);\n *\n * // In hook - use directly with useSelector, no shallowEqual needed\n * export function useRampsGeolocation() {\n * const { isFetching, error } = useSelector(selectGeolocationRequest);\n * // ... rest of hook\n * }\n * ```\n *\n * @example\n * ```ts\n * // For methods with parameters\n * export const selectCryptoCurrenciesRequest = (region: string) =>\n * createRequestSelector<RootState, CryptoCurrency[]>(\n * selectRampsControllerState,\n * 'getCryptoCurrencies',\n * [region],\n * );\n *\n * // In component\n * const { data, isFetching, error } = useSelector(\n * selectCryptoCurrenciesRequest('US')\n * );\n * ```\n */\nexport function createRequestSelector<TRootState, TData>(\n getState: (rootState: TRootState) => RampsControllerState | undefined,\n method: string,\n params: unknown[],\n): (state: TRootState) => RequestSelectorResult<TData> {\n const cacheKey = createCacheKey(method, params);\n\n let lastRequest: RequestState | undefined;\n let lastResult: RequestSelectorResult<TData> | null = null;\n\n return (state: TRootState): RequestSelectorResult<TData> => {\n const request = getState(state)?.requests?.[cacheKey];\n\n if (request === lastRequest && lastResult !== null) {\n return lastResult;\n }\n\n lastRequest = request;\n lastResult = {\n data: (request?.data as TData) ?? null,\n isFetching: request?.status === RequestStatus.LOADING,\n error: request?.error ?? null,\n };\n\n return lastResult;\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask/ramps-controller",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "A controller for managing cryptocurrency on/off ramps functionality",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"build:docs": "typedoc",
|
|
41
41
|
"changelog:update": "../../scripts/update-changelog.sh @metamask/ramps-controller",
|
|
42
42
|
"changelog:validate": "../../scripts/validate-changelog.sh @metamask/ramps-controller",
|
|
43
|
+
"dev": "node dev-watch.js",
|
|
43
44
|
"publish:preview": "yarn npm publish --tag preview",
|
|
44
45
|
"since-latest-release": "../../scripts/since-latest-release.sh",
|
|
45
46
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter",
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
},
|
|
50
51
|
"dependencies": {
|
|
51
52
|
"@metamask/base-controller": "^9.0.0",
|
|
52
|
-
"@metamask/controller-utils": "^11.
|
|
53
|
+
"@metamask/controller-utils": "^11.17.0",
|
|
53
54
|
"@metamask/messenger": "^0.3.0"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OnRampService-method-action-types.cjs","sourceRoot":"","sources":["../src/OnRampService-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { OnRampService } from './OnRampService';\n\n/**\n * Makes a request to the API in order to retrieve the user's geolocation\n * based on their IP address.\n *\n * @returns The user's country/region code (e.g., \"US-UT\" for Utah, USA).\n */\nexport type OnRampServiceGetGeolocationAction = {\n type: `OnRampService:getGeolocation`;\n handler: OnRampService['getGeolocation'];\n};\n\n/**\n * Union of all OnRampService action types.\n */\nexport type OnRampServiceMethodActions = OnRampServiceGetGeolocationAction;\n"]}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is auto generated by `scripts/generate-method-action-types.ts`.
|
|
3
|
-
* Do not edit manually.
|
|
4
|
-
*/
|
|
5
|
-
import type { OnRampService } from "./OnRampService.cjs";
|
|
6
|
-
/**
|
|
7
|
-
* Makes a request to the API in order to retrieve the user's geolocation
|
|
8
|
-
* based on their IP address.
|
|
9
|
-
*
|
|
10
|
-
* @returns The user's country/region code (e.g., "US-UT" for Utah, USA).
|
|
11
|
-
*/
|
|
12
|
-
export type OnRampServiceGetGeolocationAction = {
|
|
13
|
-
type: `OnRampService:getGeolocation`;
|
|
14
|
-
handler: OnRampService['getGeolocation'];
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Union of all OnRampService action types.
|
|
18
|
-
*/
|
|
19
|
-
export type OnRampServiceMethodActions = OnRampServiceGetGeolocationAction;
|
|
20
|
-
//# sourceMappingURL=OnRampService-method-action-types.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OnRampService-method-action-types.d.cts","sourceRoot":"","sources":["../src/OnRampService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,4BAAwB;AAErD;;;;;GAKG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;CAC1C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG,iCAAiC,CAAC"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is auto generated by `scripts/generate-method-action-types.ts`.
|
|
3
|
-
* Do not edit manually.
|
|
4
|
-
*/
|
|
5
|
-
import type { OnRampService } from "./OnRampService.mjs";
|
|
6
|
-
/**
|
|
7
|
-
* Makes a request to the API in order to retrieve the user's geolocation
|
|
8
|
-
* based on their IP address.
|
|
9
|
-
*
|
|
10
|
-
* @returns The user's country/region code (e.g., "US-UT" for Utah, USA).
|
|
11
|
-
*/
|
|
12
|
-
export type OnRampServiceGetGeolocationAction = {
|
|
13
|
-
type: `OnRampService:getGeolocation`;
|
|
14
|
-
handler: OnRampService['getGeolocation'];
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Union of all OnRampService action types.
|
|
18
|
-
*/
|
|
19
|
-
export type OnRampServiceMethodActions = OnRampServiceGetGeolocationAction;
|
|
20
|
-
//# sourceMappingURL=OnRampService-method-action-types.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OnRampService-method-action-types.d.mts","sourceRoot":"","sources":["../src/OnRampService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,4BAAwB;AAErD;;;;;GAKG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;CAC1C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG,iCAAiC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OnRampService-method-action-types.mjs","sourceRoot":"","sources":["../src/OnRampService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { OnRampService } from './OnRampService';\n\n/**\n * Makes a request to the API in order to retrieve the user's geolocation\n * based on their IP address.\n *\n * @returns The user's country/region code (e.g., \"US-UT\" for Utah, USA).\n */\nexport type OnRampServiceGetGeolocationAction = {\n type: `OnRampService:getGeolocation`;\n handler: OnRampService['getGeolocation'];\n};\n\n/**\n * Union of all OnRampService action types.\n */\nexport type OnRampServiceMethodActions = OnRampServiceGetGeolocationAction;\n"]}
|
package/dist/OnRampService.cjs
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
-
};
|
|
8
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
-
};
|
|
13
|
-
var _a, _OnRampService_messenger, _OnRampService_fetch, _OnRampService_policy, _OnRampService_baseUrl;
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.OnRampService = exports.OnRampEnvironment = exports.serviceName = void 0;
|
|
16
|
-
const controller_utils_1 = require("@metamask/controller-utils");
|
|
17
|
-
// === GENERAL ===
|
|
18
|
-
/**
|
|
19
|
-
* The name of the {@link OnRampService}, used to namespace the
|
|
20
|
-
* service's actions and events.
|
|
21
|
-
*/
|
|
22
|
-
exports.serviceName = 'OnRampService';
|
|
23
|
-
/**
|
|
24
|
-
* The environment to use for API requests.
|
|
25
|
-
*/
|
|
26
|
-
var OnRampEnvironment;
|
|
27
|
-
(function (OnRampEnvironment) {
|
|
28
|
-
OnRampEnvironment["Production"] = "production";
|
|
29
|
-
OnRampEnvironment["Staging"] = "staging";
|
|
30
|
-
OnRampEnvironment["Development"] = "development";
|
|
31
|
-
})(OnRampEnvironment || (exports.OnRampEnvironment = OnRampEnvironment = {}));
|
|
32
|
-
// === MESSENGER ===
|
|
33
|
-
const MESSENGER_EXPOSED_METHODS = ['getGeolocation'];
|
|
34
|
-
// === SERVICE DEFINITION ===
|
|
35
|
-
/**
|
|
36
|
-
* Gets the base URL for API requests based on the environment.
|
|
37
|
-
*
|
|
38
|
-
* @param environment - The environment to use.
|
|
39
|
-
* @returns The base URL for API requests.
|
|
40
|
-
*/
|
|
41
|
-
function getBaseUrl(environment) {
|
|
42
|
-
switch (environment) {
|
|
43
|
-
case OnRampEnvironment.Production:
|
|
44
|
-
return 'https://on-ramp.api.cx.metamask.io';
|
|
45
|
-
case OnRampEnvironment.Staging:
|
|
46
|
-
return 'https://on-ramp.uat-api.cx.metamask.io';
|
|
47
|
-
case OnRampEnvironment.Development:
|
|
48
|
-
return 'http://localhost:3000';
|
|
49
|
-
default:
|
|
50
|
-
throw new Error(`Invalid environment: ${String(environment)}`);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* This service object is responsible for interacting with the OnRamp API.
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
*
|
|
58
|
-
* ``` ts
|
|
59
|
-
* import { Messenger } from '@metamask/messenger';
|
|
60
|
-
* import type {
|
|
61
|
-
* OnRampServiceActions,
|
|
62
|
-
* OnRampServiceEvents,
|
|
63
|
-
* } from '@metamask/ramps-controller';
|
|
64
|
-
*
|
|
65
|
-
* const rootMessenger = new Messenger<
|
|
66
|
-
* 'Root',
|
|
67
|
-
* OnRampServiceActions
|
|
68
|
-
* OnRampServiceEvents
|
|
69
|
-
* >({ namespace: 'Root' });
|
|
70
|
-
* const onRampServiceMessenger = new Messenger<
|
|
71
|
-
* 'OnRampService',
|
|
72
|
-
* OnRampServiceActions,
|
|
73
|
-
* OnRampServiceEvents,
|
|
74
|
-
* typeof rootMessenger,
|
|
75
|
-
* >({
|
|
76
|
-
* namespace: 'OnRampService',
|
|
77
|
-
* parent: rootMessenger,
|
|
78
|
-
* });
|
|
79
|
-
* // Instantiate the service to register its actions on the messenger
|
|
80
|
-
* new OnRampService({
|
|
81
|
-
* messenger: onRampServiceMessenger,
|
|
82
|
-
* environment: OnRampEnvironment.Production,
|
|
83
|
-
* fetch,
|
|
84
|
-
* });
|
|
85
|
-
*
|
|
86
|
-
* // Later...
|
|
87
|
-
* // Get the user's geolocation
|
|
88
|
-
* const geolocation = await rootMessenger.call(
|
|
89
|
-
* 'OnRampService:getGeolocation',
|
|
90
|
-
* );
|
|
91
|
-
* // ... Do something with the geolocation ...
|
|
92
|
-
* ```
|
|
93
|
-
*/
|
|
94
|
-
class OnRampService {
|
|
95
|
-
/**
|
|
96
|
-
* Constructs a new OnRampService object.
|
|
97
|
-
*
|
|
98
|
-
* @param args - The constructor arguments.
|
|
99
|
-
* @param args.messenger - The messenger suited for this service.
|
|
100
|
-
* @param args.environment - The environment to use for API requests.
|
|
101
|
-
* @param args.fetch - A function that can be used to make an HTTP request. If
|
|
102
|
-
* your JavaScript environment supports `fetch` natively, you'll probably want
|
|
103
|
-
* to pass that; otherwise you can pass an equivalent (such as `fetch` via
|
|
104
|
-
* `node-fetch`).
|
|
105
|
-
* @param args.policyOptions - Options to pass to `createServicePolicy`, which
|
|
106
|
-
* is used to wrap each request. See {@link CreateServicePolicyOptions}.
|
|
107
|
-
*/
|
|
108
|
-
constructor({ messenger, environment = OnRampEnvironment.Staging, fetch: fetchFunction, policyOptions = {}, }) {
|
|
109
|
-
/**
|
|
110
|
-
* The messenger suited for this service.
|
|
111
|
-
*/
|
|
112
|
-
_OnRampService_messenger.set(this, void 0);
|
|
113
|
-
/**
|
|
114
|
-
* A function that can be used to make an HTTP request.
|
|
115
|
-
*/
|
|
116
|
-
_OnRampService_fetch.set(this, void 0);
|
|
117
|
-
/**
|
|
118
|
-
* The policy that wraps the request.
|
|
119
|
-
*
|
|
120
|
-
* @see {@link createServicePolicy}
|
|
121
|
-
*/
|
|
122
|
-
_OnRampService_policy.set(this, void 0);
|
|
123
|
-
/**
|
|
124
|
-
* The base URL for API requests.
|
|
125
|
-
*/
|
|
126
|
-
_OnRampService_baseUrl.set(this, void 0);
|
|
127
|
-
this.name = exports.serviceName;
|
|
128
|
-
__classPrivateFieldSet(this, _OnRampService_messenger, messenger, "f");
|
|
129
|
-
__classPrivateFieldSet(this, _OnRampService_fetch, fetchFunction, "f");
|
|
130
|
-
__classPrivateFieldSet(this, _OnRampService_policy, (0, controller_utils_1.createServicePolicy)(policyOptions), "f");
|
|
131
|
-
__classPrivateFieldSet(this, _OnRampService_baseUrl, getBaseUrl(environment), "f");
|
|
132
|
-
__classPrivateFieldGet(this, _OnRampService_messenger, "f").registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Registers a handler that will be called after a request returns a non-500
|
|
136
|
-
* response, causing a retry. Primarily useful in tests where timers are being
|
|
137
|
-
* mocked.
|
|
138
|
-
*
|
|
139
|
-
* @param listener - The handler to be called.
|
|
140
|
-
* @returns An object that can be used to unregister the handler. See
|
|
141
|
-
* {@link CockatielEvent}.
|
|
142
|
-
* @see {@link createServicePolicy}
|
|
143
|
-
*/
|
|
144
|
-
onRetry(listener) {
|
|
145
|
-
return __classPrivateFieldGet(this, _OnRampService_policy, "f").onRetry(listener);
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Registers a handler that will be called after a set number of retry rounds
|
|
149
|
-
* prove that requests to the API endpoint consistently return a 5xx response.
|
|
150
|
-
*
|
|
151
|
-
* @param listener - The handler to be called.
|
|
152
|
-
* @returns An object that can be used to unregister the handler. See
|
|
153
|
-
* {@link CockatielEvent}.
|
|
154
|
-
* @see {@link createServicePolicy}
|
|
155
|
-
*/
|
|
156
|
-
onBreak(listener) {
|
|
157
|
-
return __classPrivateFieldGet(this, _OnRampService_policy, "f").onBreak(listener);
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Registers a handler that will be called under one of two circumstances:
|
|
161
|
-
*
|
|
162
|
-
* 1. After a set number of retries prove that requests to the API
|
|
163
|
-
* consistently result in one of the following failures:
|
|
164
|
-
* 1. A connection initiation error
|
|
165
|
-
* 2. A connection reset error
|
|
166
|
-
* 3. A timeout error
|
|
167
|
-
* 4. A non-JSON response
|
|
168
|
-
* 5. A 502, 503, or 504 response
|
|
169
|
-
* 2. After a successful request is made to the API, but the response takes
|
|
170
|
-
* longer than a set duration to return.
|
|
171
|
-
*
|
|
172
|
-
* @param listener - The handler to be called.
|
|
173
|
-
* @returns An object that can be used to unregister the handler. See
|
|
174
|
-
* {@link CockatielEvent}.
|
|
175
|
-
*/
|
|
176
|
-
onDegraded(listener) {
|
|
177
|
-
return __classPrivateFieldGet(this, _OnRampService_policy, "f").onDegraded(listener);
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Makes a request to the API in order to retrieve the user's geolocation
|
|
181
|
-
* based on their IP address.
|
|
182
|
-
*
|
|
183
|
-
* @returns The user's country/region code (e.g., "US-UT" for Utah, USA).
|
|
184
|
-
*/
|
|
185
|
-
async getGeolocation() {
|
|
186
|
-
const response = await __classPrivateFieldGet(this, _OnRampService_policy, "f").execute(async () => {
|
|
187
|
-
const url = new URL('geolocation', __classPrivateFieldGet(this, _OnRampService_baseUrl, "f"));
|
|
188
|
-
const localResponse = await __classPrivateFieldGet(this, _OnRampService_fetch, "f").call(this, url);
|
|
189
|
-
if (!localResponse.ok) {
|
|
190
|
-
throw new controller_utils_1.HttpError(localResponse.status, `Fetching '${url.toString()}' failed with status '${localResponse.status}'`);
|
|
191
|
-
}
|
|
192
|
-
return localResponse;
|
|
193
|
-
});
|
|
194
|
-
const textResponse = await response.text();
|
|
195
|
-
const trimmedResponse = textResponse.trim();
|
|
196
|
-
if (trimmedResponse.length > 0) {
|
|
197
|
-
return trimmedResponse;
|
|
198
|
-
}
|
|
199
|
-
throw new Error('Malformed response received from geolocation API');
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
exports.OnRampService = OnRampService;
|
|
203
|
-
_a = OnRampService, _OnRampService_messenger = new WeakMap(), _OnRampService_fetch = new WeakMap(), _OnRampService_policy = new WeakMap(), _OnRampService_baseUrl = new WeakMap();
|
|
204
|
-
//# sourceMappingURL=OnRampService.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OnRampService.cjs","sourceRoot":"","sources":["../src/OnRampService.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\n\nimport type { OnRampServiceMethodActions } from './OnRampService-method-action-types';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link OnRampService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'OnRampService';\n\n/**\n * The environment to use for API requests.\n */\nexport enum OnRampEnvironment {\n Production = 'production',\n Staging = 'staging',\n Development = 'development',\n}\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['getGeolocation'] as const;\n\n/**\n * Actions that {@link OnRampService} exposes to other consumers.\n */\nexport type OnRampServiceActions = OnRampServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link OnRampService} calls.\n */\ntype AllowedActions = never;\n\n/**\n * Events that {@link OnRampService} exposes to other consumers.\n */\nexport type OnRampServiceEvents = never;\n\n/**\n * Events from other messengers that {@link OnRampService} subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link OnRampService}.\n */\nexport type OnRampServiceMessenger = Messenger<\n typeof serviceName,\n OnRampServiceActions | AllowedActions,\n OnRampServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\n/**\n * Gets the base URL for API requests based on the environment.\n *\n * @param environment - The environment to use.\n * @returns The base URL for API requests.\n */\nfunction getBaseUrl(environment: OnRampEnvironment): string {\n switch (environment) {\n case OnRampEnvironment.Production:\n return 'https://on-ramp.api.cx.metamask.io';\n case OnRampEnvironment.Staging:\n return 'https://on-ramp.uat-api.cx.metamask.io';\n case OnRampEnvironment.Development:\n return 'http://localhost:3000';\n default:\n throw new Error(`Invalid environment: ${String(environment)}`);\n }\n}\n\n/**\n * This service object is responsible for interacting with the OnRamp API.\n *\n * @example\n *\n * ``` ts\n * import { Messenger } from '@metamask/messenger';\n * import type {\n * OnRampServiceActions,\n * OnRampServiceEvents,\n * } from '@metamask/ramps-controller';\n *\n * const rootMessenger = new Messenger<\n * 'Root',\n * OnRampServiceActions\n * OnRampServiceEvents\n * >({ namespace: 'Root' });\n * const onRampServiceMessenger = new Messenger<\n * 'OnRampService',\n * OnRampServiceActions,\n * OnRampServiceEvents,\n * typeof rootMessenger,\n * >({\n * namespace: 'OnRampService',\n * parent: rootMessenger,\n * });\n * // Instantiate the service to register its actions on the messenger\n * new OnRampService({\n * messenger: onRampServiceMessenger,\n * environment: OnRampEnvironment.Production,\n * fetch,\n * });\n *\n * // Later...\n * // Get the user's geolocation\n * const geolocation = await rootMessenger.call(\n * 'OnRampService:getGeolocation',\n * );\n * // ... Do something with the geolocation ...\n * ```\n */\nexport class OnRampService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ConstructorParameters<\n typeof OnRampService\n >[0]['messenger'];\n\n /**\n * A function that can be used to make an HTTP request.\n */\n readonly #fetch: ConstructorParameters<typeof OnRampService>[0]['fetch'];\n\n /**\n * The policy that wraps the request.\n *\n * @see {@link createServicePolicy}\n */\n readonly #policy: ServicePolicy;\n\n /**\n * The base URL for API requests.\n */\n readonly #baseUrl: string;\n\n /**\n * Constructs a new OnRampService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.environment - The environment to use for API requests.\n * @param args.fetch - A function that can be used to make an HTTP request. If\n * your JavaScript environment supports `fetch` natively, you'll probably want\n * to pass that; otherwise you can pass an equivalent (such as `fetch` via\n * `node-fetch`).\n * @param args.policyOptions - Options to pass to `createServicePolicy`, which\n * is used to wrap each request. See {@link CreateServicePolicyOptions}.\n */\n constructor({\n messenger,\n environment = OnRampEnvironment.Staging,\n fetch: fetchFunction,\n policyOptions = {},\n }: {\n messenger: OnRampServiceMessenger;\n environment?: OnRampEnvironment;\n fetch: typeof fetch;\n policyOptions?: CreateServicePolicyOptions;\n }) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#fetch = fetchFunction;\n this.#policy = createServicePolicy(policyOptions);\n this.#baseUrl = getBaseUrl(environment);\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Registers a handler that will be called after a request returns a non-500\n * response, causing a retry. Primarily useful in tests where timers are being\n * mocked.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onRetry(\n listener: Parameters<ServicePolicy['onRetry']>[0],\n ): ReturnType<ServicePolicy['onRetry']> {\n return this.#policy.onRetry(listener);\n }\n\n /**\n * Registers a handler that will be called after a set number of retry rounds\n * prove that requests to the API endpoint consistently return a 5xx response.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onBreak(\n listener: Parameters<ServicePolicy['onBreak']>[0],\n ): ReturnType<ServicePolicy['onBreak']> {\n return this.#policy.onBreak(listener);\n }\n\n /**\n * Registers a handler that will be called under one of two circumstances:\n *\n * 1. After a set number of retries prove that requests to the API\n * consistently result in one of the following failures:\n * 1. A connection initiation error\n * 2. A connection reset error\n * 3. A timeout error\n * 4. A non-JSON response\n * 5. A 502, 503, or 504 response\n * 2. After a successful request is made to the API, but the response takes\n * longer than a set duration to return.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n */\n onDegraded(\n listener: Parameters<ServicePolicy['onDegraded']>[0],\n ): ReturnType<ServicePolicy['onDegraded']> {\n return this.#policy.onDegraded(listener);\n }\n\n /**\n * Makes a request to the API in order to retrieve the user's geolocation\n * based on their IP address.\n *\n * @returns The user's country/region code (e.g., \"US-UT\" for Utah, USA).\n */\n async getGeolocation(): Promise<string> {\n const response = await this.#policy.execute(async () => {\n const url = new URL('geolocation', this.#baseUrl);\n const localResponse = await this.#fetch(url);\n if (!localResponse.ok) {\n throw new HttpError(\n localResponse.status,\n `Fetching '${url.toString()}' failed with status '${localResponse.status}'`,\n );\n }\n return localResponse;\n });\n\n const textResponse = await response.text();\n const trimmedResponse = textResponse.trim();\n\n if (trimmedResponse.length > 0) {\n return trimmedResponse;\n }\n\n throw new Error('Malformed response received from geolocation API');\n }\n}\n"]}
|