@metamask-previews/core-backend 9.0.0-preview-5bb6dba48 → 9.0.0-preview-d8fceeabc
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 +4 -0
- package/dist/api/base-client.cjs +53 -27
- package/dist/api/base-client.cjs.map +1 -1
- package/dist/api/base-client.d.cts +1 -0
- package/dist/api/base-client.d.cts.map +1 -1
- package/dist/api/base-client.d.mts +1 -0
- package/dist/api/base-client.d.mts.map +1 -1
- package/dist/api/base-client.mjs +54 -28
- package/dist/api/base-client.mjs.map +1 -1
- package/dist/api/index.cjs +2 -1
- package/dist/api/index.cjs.map +1 -1
- package/dist/api/index.d.cts +1 -1
- package/dist/api/index.d.cts.map +1 -1
- package/dist/api/index.d.mts +1 -1
- package/dist/api/index.d.mts.map +1 -1
- package/dist/api/index.mjs +1 -1
- package/dist/api/index.mjs.map +1 -1
- package/dist/api/shared-types.cjs +6 -2
- package/dist/api/shared-types.cjs.map +1 -1
- package/dist/api/shared-types.d.cts +12 -1
- package/dist/api/shared-types.d.cts.map +1 -1
- package/dist/api/shared-types.d.mts +12 -1
- package/dist/api/shared-types.d.mts.map +1 -1
- package/dist/api/shared-types.mjs +5 -1
- package/dist/api/shared-types.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,11 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
### Added
|
|
11
11
|
|
|
12
|
+
- Add `authTokenTimeout` to `ApiPlatformClientOptions` and export `DEFAULT_AUTH_TOKEN_TIMEOUT` ([#10104](https://github.com/MetaMask/core/pull/10104))
|
|
13
|
+
- Requests wait at most this long (default 500ms) for `getBearerToken`. If the token is not ready, the request is sent unauthenticated while the in-flight `fetchQuery` continues so later requests can attach the token. Set `authTokenTimeout` to `0` to wait indefinitely.
|
|
14
|
+
- Bearer-token `fetchQuery` uses `staleTime: 0` so concurrent requests are de-duplicated without a second JWT cache; token lifetime stays with AuthenticationController.
|
|
12
15
|
- Add `bypassServerCache` option to `FetchOptions` ([#10068](https://github.com/MetaMask/core/pull/10068))
|
|
13
16
|
- When true, the v5/v6 multi-account balances requests skip the client-side query cache (stale time defaults to 0) and append a random `bypassServerCache` query param so the Accounts API's server-side cache (keyed on the full URL) misses. Intended for hard refreshes only, e.g. right after a transaction confirms.
|
|
14
17
|
|
|
15
18
|
### Changed
|
|
16
19
|
|
|
20
|
+
- Bearer-token `fetchQuery` no longer uses a 5-minute `STALE_TIMES.AUTH_TOKEN`; `STALE_TIMES.AUTH_TOKEN` is removed ([#10104](https://github.com/MetaMask/core/pull/10104))
|
|
17
21
|
- Bump `@metamask/remote-feature-flag-controller` from `^6.0.0` to `^6.1.0` ([#9980](https://github.com/MetaMask/core/pull/9980))
|
|
18
22
|
- Bump `@metamask/utils` from `^11.11.0` to `^11.12.0` ([#10076](https://github.com/MetaMask/core/pull/10076))
|
|
19
23
|
- Bump `@metamask/account-tree-controller` from `^8.0.0` to `^8.1.0` ([#10088](https://github.com/MetaMask/core/pull/10088))
|
package/dist/api/base-client.cjs
CHANGED
|
@@ -13,7 +13,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
13
13
|
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");
|
|
14
14
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
15
15
|
};
|
|
16
|
-
var _BaseApiClient_queryClientInstance;
|
|
16
|
+
var _BaseApiClient_instances, _BaseApiClient_queryClientInstance, _BaseApiClient_fetchBearerToken;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.HttpError = exports.GC_TIMES = exports.STALE_TIMES = exports.API_URLS = exports.BaseApiClient = exports.authQueryKeys = void 0;
|
|
19
19
|
const query_core_1 = require("@tanstack/query-core");
|
|
@@ -53,10 +53,13 @@ class BaseApiClient {
|
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
constructor(options) {
|
|
56
|
+
_BaseApiClient_instances.add(this);
|
|
56
57
|
_BaseApiClient_queryClientInstance.set(this, void 0);
|
|
57
58
|
this.clientProduct = options.clientProduct;
|
|
58
59
|
this.clientVersion = options.clientVersion;
|
|
59
60
|
this.getBearerToken = options.getBearerToken;
|
|
61
|
+
this.authTokenTimeout =
|
|
62
|
+
options.authTokenTimeout ?? shared_types_js_1.DEFAULT_AUTH_TOKEN_TIMEOUT;
|
|
60
63
|
__classPrivateFieldSet(this, _BaseApiClient_queryClientInstance, options.queryClient ??
|
|
61
64
|
new query_core_1.QueryClient({
|
|
62
65
|
defaultOptions: {
|
|
@@ -102,31 +105,9 @@ class BaseApiClient {
|
|
|
102
105
|
if (this.clientVersion) {
|
|
103
106
|
headers['x-metamask-clientversion'] = this.clientVersion;
|
|
104
107
|
}
|
|
105
|
-
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
const { getBearerToken } = this;
|
|
109
|
-
try {
|
|
110
|
-
// fetchQuery handles caching and deduplicates concurrent requests
|
|
111
|
-
const token = await __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f").fetchQuery({
|
|
112
|
-
queryKey,
|
|
113
|
-
queryFn: async () => {
|
|
114
|
-
const result = await getBearerToken();
|
|
115
|
-
// Throw if no token - prevents caching null/undefined
|
|
116
|
-
// so subsequent requests can retry (e.g., after user logs in)
|
|
117
|
-
if (!result) {
|
|
118
|
-
throw new Error('No bearer token available');
|
|
119
|
-
}
|
|
120
|
-
return result;
|
|
121
|
-
},
|
|
122
|
-
staleTime: shared_types_js_1.STALE_TIMES.AUTH_TOKEN,
|
|
123
|
-
retry: false, // Don't retry auth failures
|
|
124
|
-
});
|
|
125
|
-
headers.Authorization = `Bearer ${token}`;
|
|
126
|
-
}
|
|
127
|
-
catch {
|
|
128
|
-
// No token available - continue without auth header
|
|
129
|
-
}
|
|
108
|
+
const token = await __classPrivateFieldGet(this, _BaseApiClient_instances, "m", _BaseApiClient_fetchBearerToken).call(this);
|
|
109
|
+
if (token) {
|
|
110
|
+
headers.Authorization = `Bearer ${token}`;
|
|
130
111
|
}
|
|
131
112
|
const response = await fetch(url.toString(), {
|
|
132
113
|
method: 'GET',
|
|
@@ -147,5 +128,50 @@ class BaseApiClient {
|
|
|
147
128
|
}
|
|
148
129
|
}
|
|
149
130
|
exports.BaseApiClient = BaseApiClient;
|
|
150
|
-
_BaseApiClient_queryClientInstance = new WeakMap()
|
|
131
|
+
_BaseApiClient_queryClientInstance = new WeakMap(), _BaseApiClient_instances = new WeakSet(), _BaseApiClient_fetchBearerToken =
|
|
132
|
+
/**
|
|
133
|
+
* Resolve the bearer token, giving up after `authTokenTimeout` so that a slow
|
|
134
|
+
* token provider does not delay the request. When the wait times out the
|
|
135
|
+
* request goes out unauthenticated (lower rate limit) while the in-flight
|
|
136
|
+
* `fetchQuery` keeps resolving `getBearerToken` for later requests.
|
|
137
|
+
*
|
|
138
|
+
* @returns The bearer token, or undefined if unavailable in time.
|
|
139
|
+
*/
|
|
140
|
+
async function _BaseApiClient_fetchBearerToken() {
|
|
141
|
+
const { getBearerToken } = this;
|
|
142
|
+
if (!getBearerToken) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
// fetchQuery de-duplicates concurrent callers. staleTime is 0 so we do not
|
|
146
|
+
// cache the JWT here — AuthenticationController already owns token lifetime.
|
|
147
|
+
const tokenPromise = __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f")
|
|
148
|
+
.fetchQuery({
|
|
149
|
+
queryKey: exports.authQueryKeys.bearerToken(),
|
|
150
|
+
queryFn: async () => {
|
|
151
|
+
const result = await getBearerToken();
|
|
152
|
+
// Throw if no token - prevents caching null/undefined
|
|
153
|
+
// so subsequent requests can retry (e.g., after user logs in)
|
|
154
|
+
if (!result) {
|
|
155
|
+
throw new Error('No bearer token available');
|
|
156
|
+
}
|
|
157
|
+
return result;
|
|
158
|
+
},
|
|
159
|
+
staleTime: 0,
|
|
160
|
+
retry: false, // Don't retry auth failures
|
|
161
|
+
})
|
|
162
|
+
.catch(() => undefined);
|
|
163
|
+
if (this.authTokenTimeout <= 0) {
|
|
164
|
+
return await tokenPromise;
|
|
165
|
+
}
|
|
166
|
+
let timeoutId;
|
|
167
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
168
|
+
timeoutId = setTimeout(() => resolve(undefined), this.authTokenTimeout);
|
|
169
|
+
});
|
|
170
|
+
try {
|
|
171
|
+
return await Promise.race([tokenPromise, timeoutPromise]);
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
clearTimeout(timeoutId);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
151
177
|
//# sourceMappingURL=base-client.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-client.cjs","sourceRoot":"","sources":["../../src/api/base-client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Base API Client - Shared HTTP functionality for all API clients.\n */\n\nimport { QueryClient } from '@tanstack/query-core';\nimport type { QueryKey } from '@tanstack/query-core';\n\nimport {\n API_URLS,\n STALE_TIMES,\n GC_TIMES,\n calculateRetryDelay,\n shouldRetry,\n HttpError,\n} from './shared-types.js';\nimport type { ApiPlatformClientOptions } from './shared-types.js';\n\n// Auth query keys - shared for token management across clients\nexport const authQueryKeys = {\n bearerToken: (): QueryKey => ['auth', 'bearerToken'],\n} as const;\n\nexport type { ApiPlatformClientOptions };\n\n/**\n * Internal fetch options for HTTP requests.\n */\nexport type InternalFetchOptions = {\n signal?: AbortSignal;\n params?: Record<\n string,\n string | string[] | number | number[] | boolean | undefined\n >;\n};\n\n/**\n * Base API Client with shared HTTP and caching functionality.\n * Extended by all specific API clients.\n */\nexport class BaseApiClient {\n protected readonly clientProduct: string;\n\n protected readonly clientVersion?: string;\n\n protected readonly getBearerToken?: () => Promise<string | undefined>;\n\n readonly #queryClientInstance: QueryClient;\n\n /**\n * Get the underlying QueryClient instance.\n * Exposed for cache management operations.\n *\n * @returns The QueryClient instance.\n */\n get queryClient(): QueryClient {\n return this.#queryClientInstance;\n }\n\n /**\n * Invalidate the cached auth token.\n * Call this when the user logs out or the token expires.\n *\n * Uses resetQueries() instead of invalidateQueries() to completely remove\n * the cached value, ensuring the next request fetches a fresh token immediately.\n */\n async invalidateAuthToken(): Promise<void> {\n await this.#queryClientInstance.resetQueries({\n queryKey: authQueryKeys.bearerToken(),\n });\n }\n\n constructor(options: ApiPlatformClientOptions) {\n this.clientProduct = options.clientProduct;\n this.clientVersion = options.clientVersion;\n this.getBearerToken = options.getBearerToken;\n\n this.#queryClientInstance =\n options.queryClient ??\n new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: STALE_TIMES.DEFAULT,\n gcTime: GC_TIMES.DEFAULT,\n retry: shouldRetry,\n retryDelay: calculateRetryDelay,\n refetchOnWindowFocus: false,\n networkMode: 'always',\n },\n },\n });\n }\n\n /**\n * Internal HTTP fetch method with authentication and error handling.\n *\n * @param baseUrl - The base URL for the API.\n * @param path - The API endpoint path.\n * @param options - Optional fetch configuration.\n * @returns The parsed JSON response.\n */\n protected async fetch<ResponseType>(\n baseUrl: string,\n path: string,\n options?: InternalFetchOptions,\n ): Promise<ResponseType> {\n const url = new URL(path, baseUrl);\n\n if (options?.params) {\n for (const [key, value] of Object.entries(options.params)) {\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n // Convert array values (including number[]) to comma-separated string\n url.searchParams.set(key, value.map(String).join(','));\n } else {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-metamask-clientproduct': this.clientProduct,\n };\n\n if (this.clientVersion) {\n headers['x-metamask-clientversion'] = this.clientVersion;\n }\n\n // Get bearer token using fetchQuery for automatic deduplication\n if (this.getBearerToken) {\n const queryKey = authQueryKeys.bearerToken();\n const { getBearerToken } = this;\n\n try {\n // fetchQuery handles caching and deduplicates concurrent requests\n const token = await this.#queryClientInstance.fetchQuery({\n queryKey,\n queryFn: async () => {\n const result = await getBearerToken();\n // Throw if no token - prevents caching null/undefined\n // so subsequent requests can retry (e.g., after user logs in)\n if (!result) {\n throw new Error('No bearer token available');\n }\n return result;\n },\n staleTime: STALE_TIMES.AUTH_TOKEN,\n retry: false, // Don't retry auth failures\n });\n\n headers.Authorization = `Bearer ${token}`;\n } catch {\n // No token available - continue without auth header\n }\n }\n\n const response = await fetch(url.toString(), {\n method: 'GET',\n headers,\n signal: options?.signal,\n });\n\n if (!response.ok) {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n // Response body is not JSON or is empty, leave body as undefined\n }\n throw new HttpError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n response.statusText,\n url.toString(),\n body,\n );\n }\n\n return response.json() as Promise<ResponseType>;\n }\n}\n\n// Re-export constants for use by API clients\nexport { API_URLS, STALE_TIMES, GC_TIMES, HttpError };\n"]}
|
|
1
|
+
{"version":3,"file":"base-client.cjs","sourceRoot":"","sources":["../../src/api/base-client.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;AAEH,qDAAmD;AAGnD,wDAQ2B;AAyMlB,yFAhNP,0BAAQ,OAgNO;AAAE,4FA/MjB,6BAAW,OA+MiB;AAAE,yFA9M9B,0BAAQ,OA8M8B;AAAE,0FA1MxC,2BAAS,OA0MwC;AAtMnD,+DAA+D;AAClD,QAAA,aAAa,GAAG;IAC3B,WAAW,EAAE,GAAa,EAAE,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC;CAC5C,CAAC;AAeX;;;GAGG;AACH,MAAa,aAAa;IAWxB;;;;;OAKG;IACH,IAAI,WAAW;QACb,OAAO,uBAAA,IAAI,0CAAqB,CAAC;IACnC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,mBAAmB;QACvB,MAAM,uBAAA,IAAI,0CAAqB,CAAC,YAAY,CAAC;YAC3C,QAAQ,EAAE,qBAAa,CAAC,WAAW,EAAE;SACtC,CAAC,CAAC;IACL,CAAC;IAED,YAAY,OAAiC;;QAzBpC,qDAAkC;QA0BzC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,gBAAgB;YACnB,OAAO,CAAC,gBAAgB,IAAI,4CAA0B,CAAC;QAEzD,uBAAA,IAAI,sCACF,OAAO,CAAC,WAAW;YACnB,IAAI,wBAAW,CAAC;gBACd,cAAc,EAAE;oBACd,OAAO,EAAE;wBACP,SAAS,EAAE,6BAAW,CAAC,OAAO;wBAC9B,MAAM,EAAE,0BAAQ,CAAC,OAAO;wBACxB,KAAK,EAAE,6BAAW;wBAClB,UAAU,EAAE,qCAAmB;wBAC/B,oBAAoB,EAAE,KAAK;wBAC3B,WAAW,EAAE,QAAQ;qBACtB;iBACF;aACF,CAAC,MAAA,CAAC;IACP,CAAC;IAmDD;;;;;;;OAOG;IACO,KAAK,CAAC,KAAK,CACnB,OAAe,EACf,IAAY,EACZ,OAA8B;QAE9B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEnC,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;YACpB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBACxB,SAAS;gBACX,CAAC;gBACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,sEAAsE;oBACtE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBACzD,CAAC;qBAAM,CAAC;oBACN,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC3C,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;YAClC,0BAA0B,EAAE,IAAI,CAAC,aAAa;SAC/C,CAAC;QAEF,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,OAAO,CAAC,0BAA0B,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC;QAC3D,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,uBAAA,IAAI,iEAAkB,MAAtB,IAAI,CAAoB,CAAC;QAC7C,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,aAAa,GAAG,UAAU,KAAK,EAAE,CAAC;QAC5C,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YAC3C,MAAM,EAAE,KAAK;YACb,OAAO;YACP,MAAM,EAAE,OAAO,EAAE,MAAM;SACxB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,IAAI,IAAa,CAAC;YAClB,IAAI,CAAC;gBACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC/B,CAAC;YAAC,MAAM,CAAC;gBACP,iEAAiE;YACnE,CAAC;YACD,MAAM,IAAI,2BAAS,CACjB,QAAQ,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,EACjD,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,UAAU,EACnB,GAAG,CAAC,QAAQ,EAAE,EACd,IAAI,CACL,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAA2B,CAAC;IAClD,CAAC;CACF;AA7KD,sCA6KC;;AApHC;;;;;;;GAOG;AACH,KAAK;IACH,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;IAChC,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,2EAA2E;IAC3E,6EAA6E;IAC7E,MAAM,YAAY,GAAG,uBAAA,IAAI,0CAAqB;SAC3C,UAAU,CAAC;QACV,QAAQ,EAAE,qBAAa,CAAC,WAAW,EAAE;QACrC,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;YACtC,sDAAsD;YACtD,8DAA8D;YAC9D,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC/C,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,SAAS,EAAE,CAAC;QACZ,KAAK,EAAE,KAAK,EAAE,4BAA4B;KAC3C,CAAC;SACD,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAE1B,IAAI,IAAI,CAAC,gBAAgB,IAAI,CAAC,EAAE,CAAC;QAC/B,OAAO,MAAM,YAAY,CAAC;IAC5B,CAAC;IAED,IAAI,SAAoD,CAAC;IACzD,MAAM,cAAc,GAAG,IAAI,OAAO,CAAY,CAAC,OAAO,EAAE,EAAE;QACxD,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;IAC5D,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,SAAS,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC","sourcesContent":["/**\n * Base API Client - Shared HTTP functionality for all API clients.\n */\n\nimport { QueryClient } from '@tanstack/query-core';\nimport type { QueryKey } from '@tanstack/query-core';\n\nimport {\n API_URLS,\n STALE_TIMES,\n GC_TIMES,\n DEFAULT_AUTH_TOKEN_TIMEOUT,\n calculateRetryDelay,\n shouldRetry,\n HttpError,\n} from './shared-types.js';\nimport type { ApiPlatformClientOptions } from './shared-types.js';\n\n// Auth query keys - shared for token management across clients\nexport const authQueryKeys = {\n bearerToken: (): QueryKey => ['auth', 'bearerToken'],\n} as const;\n\nexport type { ApiPlatformClientOptions };\n\n/**\n * Internal fetch options for HTTP requests.\n */\nexport type InternalFetchOptions = {\n signal?: AbortSignal;\n params?: Record<\n string,\n string | string[] | number | number[] | boolean | undefined\n >;\n};\n\n/**\n * Base API Client with shared HTTP and caching functionality.\n * Extended by all specific API clients.\n */\nexport class BaseApiClient {\n protected readonly clientProduct: string;\n\n protected readonly clientVersion?: string;\n\n protected readonly getBearerToken?: () => Promise<string | undefined>;\n\n protected readonly authTokenTimeout: number;\n\n readonly #queryClientInstance: QueryClient;\n\n /**\n * Get the underlying QueryClient instance.\n * Exposed for cache management operations.\n *\n * @returns The QueryClient instance.\n */\n get queryClient(): QueryClient {\n return this.#queryClientInstance;\n }\n\n /**\n * Invalidate the cached auth token.\n * Call this when the user logs out or the token expires.\n *\n * Uses resetQueries() instead of invalidateQueries() to completely remove\n * the cached value, ensuring the next request fetches a fresh token immediately.\n */\n async invalidateAuthToken(): Promise<void> {\n await this.#queryClientInstance.resetQueries({\n queryKey: authQueryKeys.bearerToken(),\n });\n }\n\n constructor(options: ApiPlatformClientOptions) {\n this.clientProduct = options.clientProduct;\n this.clientVersion = options.clientVersion;\n this.getBearerToken = options.getBearerToken;\n this.authTokenTimeout =\n options.authTokenTimeout ?? DEFAULT_AUTH_TOKEN_TIMEOUT;\n\n this.#queryClientInstance =\n options.queryClient ??\n new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: STALE_TIMES.DEFAULT,\n gcTime: GC_TIMES.DEFAULT,\n retry: shouldRetry,\n retryDelay: calculateRetryDelay,\n refetchOnWindowFocus: false,\n networkMode: 'always',\n },\n },\n });\n }\n\n /**\n * Resolve the bearer token, giving up after `authTokenTimeout` so that a slow\n * token provider does not delay the request. When the wait times out the\n * request goes out unauthenticated (lower rate limit) while the in-flight\n * `fetchQuery` keeps resolving `getBearerToken` for later requests.\n *\n * @returns The bearer token, or undefined if unavailable in time.\n */\n async #fetchBearerToken(): Promise<string | undefined> {\n const { getBearerToken } = this;\n if (!getBearerToken) {\n return undefined;\n }\n\n // fetchQuery de-duplicates concurrent callers. staleTime is 0 so we do not\n // cache the JWT here — AuthenticationController already owns token lifetime.\n const tokenPromise = this.#queryClientInstance\n .fetchQuery({\n queryKey: authQueryKeys.bearerToken(),\n queryFn: async () => {\n const result = await getBearerToken();\n // Throw if no token - prevents caching null/undefined\n // so subsequent requests can retry (e.g., after user logs in)\n if (!result) {\n throw new Error('No bearer token available');\n }\n return result;\n },\n staleTime: 0,\n retry: false, // Don't retry auth failures\n })\n .catch(() => undefined);\n\n if (this.authTokenTimeout <= 0) {\n return await tokenPromise;\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<undefined>((resolve) => {\n timeoutId = setTimeout(() => resolve(undefined), this.authTokenTimeout);\n });\n\n try {\n return await Promise.race([tokenPromise, timeoutPromise]);\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Internal HTTP fetch method with authentication and error handling.\n *\n * @param baseUrl - The base URL for the API.\n * @param path - The API endpoint path.\n * @param options - Optional fetch configuration.\n * @returns The parsed JSON response.\n */\n protected async fetch<ResponseType>(\n baseUrl: string,\n path: string,\n options?: InternalFetchOptions,\n ): Promise<ResponseType> {\n const url = new URL(path, baseUrl);\n\n if (options?.params) {\n for (const [key, value] of Object.entries(options.params)) {\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n // Convert array values (including number[]) to comma-separated string\n url.searchParams.set(key, value.map(String).join(','));\n } else {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-metamask-clientproduct': this.clientProduct,\n };\n\n if (this.clientVersion) {\n headers['x-metamask-clientversion'] = this.clientVersion;\n }\n\n const token = await this.#fetchBearerToken();\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n const response = await fetch(url.toString(), {\n method: 'GET',\n headers,\n signal: options?.signal,\n });\n\n if (!response.ok) {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n // Response body is not JSON or is empty, leave body as undefined\n }\n throw new HttpError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n response.statusText,\n url.toString(),\n body,\n );\n }\n\n return response.json() as Promise<ResponseType>;\n }\n}\n\n// Re-export constants for use by API clients\nexport { API_URLS, STALE_TIMES, GC_TIMES, HttpError };\n"]}
|
|
@@ -24,6 +24,7 @@ export declare class BaseApiClient {
|
|
|
24
24
|
protected readonly clientProduct: string;
|
|
25
25
|
protected readonly clientVersion?: string;
|
|
26
26
|
protected readonly getBearerToken?: () => Promise<string | undefined>;
|
|
27
|
+
protected readonly authTokenTimeout: number;
|
|
27
28
|
/**
|
|
28
29
|
* Get the underlying QueryClient instance.
|
|
29
30
|
* Exposed for cache management operations.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-client.d.cts","sourceRoot":"","sources":["../../src/api/base-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,6BAA6B;AAGnD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,
|
|
1
|
+
{"version":3,"file":"base-client.d.cts","sourceRoot":"","sources":["../../src/api/base-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,6BAA6B;AAGnD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EAIR,SAAS,EACV,2BAA0B;AAC3B,OAAO,KAAK,EAAE,wBAAwB,EAAE,2BAA0B;AAGlE,eAAO,MAAM,aAAa;;CAEhB,CAAC;AAEX,YAAY,EAAE,wBAAwB,EAAE,CAAC;AAEzC;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CACb,MAAM,EACN,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,GAAG,SAAS,CAC5D,CAAC;CACH,CAAC;AAEF;;;GAGG;AACH,qBAAa,aAAa;;IACxB,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAEzC,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAE1C,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEtE,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAI5C;;;;;OAKG;IACH,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED;;;;;;OAMG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;gBAM9B,OAAO,EAAE,wBAAwB;IAwE7C;;;;;;;OAOG;cACa,KAAK,CAAC,YAAY,EAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,YAAY,CAAC;CAuDzB;AAGD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -24,6 +24,7 @@ export declare class BaseApiClient {
|
|
|
24
24
|
protected readonly clientProduct: string;
|
|
25
25
|
protected readonly clientVersion?: string;
|
|
26
26
|
protected readonly getBearerToken?: () => Promise<string | undefined>;
|
|
27
|
+
protected readonly authTokenTimeout: number;
|
|
27
28
|
/**
|
|
28
29
|
* Get the underlying QueryClient instance.
|
|
29
30
|
* Exposed for cache management operations.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-client.d.mts","sourceRoot":"","sources":["../../src/api/base-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,6BAA6B;AAGnD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,
|
|
1
|
+
{"version":3,"file":"base-client.d.mts","sourceRoot":"","sources":["../../src/api/base-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,6BAA6B;AAGnD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EAIR,SAAS,EACV,2BAA0B;AAC3B,OAAO,KAAK,EAAE,wBAAwB,EAAE,2BAA0B;AAGlE,eAAO,MAAM,aAAa;;CAEhB,CAAC;AAEX,YAAY,EAAE,wBAAwB,EAAE,CAAC;AAEzC;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CACb,MAAM,EACN,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,GAAG,SAAS,CAC5D,CAAC;CACH,CAAC;AAEF;;;GAGG;AACH,qBAAa,aAAa;;IACxB,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAEzC,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAE1C,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEtE,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAI5C;;;;;OAKG;IACH,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED;;;;;;OAMG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;gBAM9B,OAAO,EAAE,wBAAwB;IAwE7C;;;;;;;OAOG;cACa,KAAK,CAAC,YAAY,EAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,YAAY,CAAC;CAuDzB;AAGD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC"}
|
package/dist/api/base-client.mjs
CHANGED
|
@@ -12,9 +12,9 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
12
12
|
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");
|
|
13
13
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
14
14
|
};
|
|
15
|
-
var _BaseApiClient_queryClientInstance;
|
|
15
|
+
var _BaseApiClient_instances, _BaseApiClient_queryClientInstance, _BaseApiClient_fetchBearerToken;
|
|
16
16
|
import { QueryClient } from "@tanstack/query-core";
|
|
17
|
-
import { API_URLS, STALE_TIMES, GC_TIMES, calculateRetryDelay, shouldRetry, HttpError } from "./shared-types.mjs";
|
|
17
|
+
import { API_URLS, STALE_TIMES, GC_TIMES, DEFAULT_AUTH_TOKEN_TIMEOUT, calculateRetryDelay, shouldRetry, HttpError } from "./shared-types.mjs";
|
|
18
18
|
// Auth query keys - shared for token management across clients
|
|
19
19
|
export const authQueryKeys = {
|
|
20
20
|
bearerToken: () => ['auth', 'bearerToken'],
|
|
@@ -46,10 +46,13 @@ export class BaseApiClient {
|
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
constructor(options) {
|
|
49
|
+
_BaseApiClient_instances.add(this);
|
|
49
50
|
_BaseApiClient_queryClientInstance.set(this, void 0);
|
|
50
51
|
this.clientProduct = options.clientProduct;
|
|
51
52
|
this.clientVersion = options.clientVersion;
|
|
52
53
|
this.getBearerToken = options.getBearerToken;
|
|
54
|
+
this.authTokenTimeout =
|
|
55
|
+
options.authTokenTimeout ?? DEFAULT_AUTH_TOKEN_TIMEOUT;
|
|
53
56
|
__classPrivateFieldSet(this, _BaseApiClient_queryClientInstance, options.queryClient ??
|
|
54
57
|
new QueryClient({
|
|
55
58
|
defaultOptions: {
|
|
@@ -95,31 +98,9 @@ export class BaseApiClient {
|
|
|
95
98
|
if (this.clientVersion) {
|
|
96
99
|
headers['x-metamask-clientversion'] = this.clientVersion;
|
|
97
100
|
}
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
|
|
101
|
-
const { getBearerToken } = this;
|
|
102
|
-
try {
|
|
103
|
-
// fetchQuery handles caching and deduplicates concurrent requests
|
|
104
|
-
const token = await __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f").fetchQuery({
|
|
105
|
-
queryKey,
|
|
106
|
-
queryFn: async () => {
|
|
107
|
-
const result = await getBearerToken();
|
|
108
|
-
// Throw if no token - prevents caching null/undefined
|
|
109
|
-
// so subsequent requests can retry (e.g., after user logs in)
|
|
110
|
-
if (!result) {
|
|
111
|
-
throw new Error('No bearer token available');
|
|
112
|
-
}
|
|
113
|
-
return result;
|
|
114
|
-
},
|
|
115
|
-
staleTime: STALE_TIMES.AUTH_TOKEN,
|
|
116
|
-
retry: false, // Don't retry auth failures
|
|
117
|
-
});
|
|
118
|
-
headers.Authorization = `Bearer ${token}`;
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
// No token available - continue without auth header
|
|
122
|
-
}
|
|
101
|
+
const token = await __classPrivateFieldGet(this, _BaseApiClient_instances, "m", _BaseApiClient_fetchBearerToken).call(this);
|
|
102
|
+
if (token) {
|
|
103
|
+
headers.Authorization = `Bearer ${token}`;
|
|
123
104
|
}
|
|
124
105
|
const response = await fetch(url.toString(), {
|
|
125
106
|
method: 'GET',
|
|
@@ -139,7 +120,52 @@ export class BaseApiClient {
|
|
|
139
120
|
return response.json();
|
|
140
121
|
}
|
|
141
122
|
}
|
|
142
|
-
_BaseApiClient_queryClientInstance = new WeakMap()
|
|
123
|
+
_BaseApiClient_queryClientInstance = new WeakMap(), _BaseApiClient_instances = new WeakSet(), _BaseApiClient_fetchBearerToken =
|
|
124
|
+
/**
|
|
125
|
+
* Resolve the bearer token, giving up after `authTokenTimeout` so that a slow
|
|
126
|
+
* token provider does not delay the request. When the wait times out the
|
|
127
|
+
* request goes out unauthenticated (lower rate limit) while the in-flight
|
|
128
|
+
* `fetchQuery` keeps resolving `getBearerToken` for later requests.
|
|
129
|
+
*
|
|
130
|
+
* @returns The bearer token, or undefined if unavailable in time.
|
|
131
|
+
*/
|
|
132
|
+
async function _BaseApiClient_fetchBearerToken() {
|
|
133
|
+
const { getBearerToken } = this;
|
|
134
|
+
if (!getBearerToken) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
// fetchQuery de-duplicates concurrent callers. staleTime is 0 so we do not
|
|
138
|
+
// cache the JWT here — AuthenticationController already owns token lifetime.
|
|
139
|
+
const tokenPromise = __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f")
|
|
140
|
+
.fetchQuery({
|
|
141
|
+
queryKey: authQueryKeys.bearerToken(),
|
|
142
|
+
queryFn: async () => {
|
|
143
|
+
const result = await getBearerToken();
|
|
144
|
+
// Throw if no token - prevents caching null/undefined
|
|
145
|
+
// so subsequent requests can retry (e.g., after user logs in)
|
|
146
|
+
if (!result) {
|
|
147
|
+
throw new Error('No bearer token available');
|
|
148
|
+
}
|
|
149
|
+
return result;
|
|
150
|
+
},
|
|
151
|
+
staleTime: 0,
|
|
152
|
+
retry: false, // Don't retry auth failures
|
|
153
|
+
})
|
|
154
|
+
.catch(() => undefined);
|
|
155
|
+
if (this.authTokenTimeout <= 0) {
|
|
156
|
+
return await tokenPromise;
|
|
157
|
+
}
|
|
158
|
+
let timeoutId;
|
|
159
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
160
|
+
timeoutId = setTimeout(() => resolve(undefined), this.authTokenTimeout);
|
|
161
|
+
});
|
|
162
|
+
try {
|
|
163
|
+
return await Promise.race([tokenPromise, timeoutPromise]);
|
|
164
|
+
}
|
|
165
|
+
finally {
|
|
166
|
+
clearTimeout(timeoutId);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
143
169
|
// Re-export constants for use by API clients
|
|
144
170
|
export { API_URLS, STALE_TIMES, GC_TIMES, HttpError };
|
|
145
171
|
//# sourceMappingURL=base-client.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-client.mjs","sourceRoot":"","sources":["../../src/api/base-client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Base API Client - Shared HTTP functionality for all API clients.\n */\n\nimport { QueryClient } from '@tanstack/query-core';\nimport type { QueryKey } from '@tanstack/query-core';\n\nimport {\n API_URLS,\n STALE_TIMES,\n GC_TIMES,\n calculateRetryDelay,\n shouldRetry,\n HttpError,\n} from './shared-types.js';\nimport type { ApiPlatformClientOptions } from './shared-types.js';\n\n// Auth query keys - shared for token management across clients\nexport const authQueryKeys = {\n bearerToken: (): QueryKey => ['auth', 'bearerToken'],\n} as const;\n\nexport type { ApiPlatformClientOptions };\n\n/**\n * Internal fetch options for HTTP requests.\n */\nexport type InternalFetchOptions = {\n signal?: AbortSignal;\n params?: Record<\n string,\n string | string[] | number | number[] | boolean | undefined\n >;\n};\n\n/**\n * Base API Client with shared HTTP and caching functionality.\n * Extended by all specific API clients.\n */\nexport class BaseApiClient {\n protected readonly clientProduct: string;\n\n protected readonly clientVersion?: string;\n\n protected readonly getBearerToken?: () => Promise<string | undefined>;\n\n readonly #queryClientInstance: QueryClient;\n\n /**\n * Get the underlying QueryClient instance.\n * Exposed for cache management operations.\n *\n * @returns The QueryClient instance.\n */\n get queryClient(): QueryClient {\n return this.#queryClientInstance;\n }\n\n /**\n * Invalidate the cached auth token.\n * Call this when the user logs out or the token expires.\n *\n * Uses resetQueries() instead of invalidateQueries() to completely remove\n * the cached value, ensuring the next request fetches a fresh token immediately.\n */\n async invalidateAuthToken(): Promise<void> {\n await this.#queryClientInstance.resetQueries({\n queryKey: authQueryKeys.bearerToken(),\n });\n }\n\n constructor(options: ApiPlatformClientOptions) {\n this.clientProduct = options.clientProduct;\n this.clientVersion = options.clientVersion;\n this.getBearerToken = options.getBearerToken;\n\n this.#queryClientInstance =\n options.queryClient ??\n new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: STALE_TIMES.DEFAULT,\n gcTime: GC_TIMES.DEFAULT,\n retry: shouldRetry,\n retryDelay: calculateRetryDelay,\n refetchOnWindowFocus: false,\n networkMode: 'always',\n },\n },\n });\n }\n\n /**\n * Internal HTTP fetch method with authentication and error handling.\n *\n * @param baseUrl - The base URL for the API.\n * @param path - The API endpoint path.\n * @param options - Optional fetch configuration.\n * @returns The parsed JSON response.\n */\n protected async fetch<ResponseType>(\n baseUrl: string,\n path: string,\n options?: InternalFetchOptions,\n ): Promise<ResponseType> {\n const url = new URL(path, baseUrl);\n\n if (options?.params) {\n for (const [key, value] of Object.entries(options.params)) {\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n // Convert array values (including number[]) to comma-separated string\n url.searchParams.set(key, value.map(String).join(','));\n } else {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-metamask-clientproduct': this.clientProduct,\n };\n\n if (this.clientVersion) {\n headers['x-metamask-clientversion'] = this.clientVersion;\n }\n\n // Get bearer token using fetchQuery for automatic deduplication\n if (this.getBearerToken) {\n const queryKey = authQueryKeys.bearerToken();\n const { getBearerToken } = this;\n\n try {\n // fetchQuery handles caching and deduplicates concurrent requests\n const token = await this.#queryClientInstance.fetchQuery({\n queryKey,\n queryFn: async () => {\n const result = await getBearerToken();\n // Throw if no token - prevents caching null/undefined\n // so subsequent requests can retry (e.g., after user logs in)\n if (!result) {\n throw new Error('No bearer token available');\n }\n return result;\n },\n staleTime: STALE_TIMES.AUTH_TOKEN,\n retry: false, // Don't retry auth failures\n });\n\n headers.Authorization = `Bearer ${token}`;\n } catch {\n // No token available - continue without auth header\n }\n }\n\n const response = await fetch(url.toString(), {\n method: 'GET',\n headers,\n signal: options?.signal,\n });\n\n if (!response.ok) {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n // Response body is not JSON or is empty, leave body as undefined\n }\n throw new HttpError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n response.statusText,\n url.toString(),\n body,\n );\n }\n\n return response.json() as Promise<ResponseType>;\n }\n}\n\n// Re-export constants for use by API clients\nexport { API_URLS, STALE_TIMES, GC_TIMES, HttpError };\n"]}
|
|
1
|
+
{"version":3,"file":"base-client.mjs","sourceRoot":"","sources":["../../src/api/base-client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Base API Client - Shared HTTP functionality for all API clients.\n */\n\nimport { QueryClient } from '@tanstack/query-core';\nimport type { QueryKey } from '@tanstack/query-core';\n\nimport {\n API_URLS,\n STALE_TIMES,\n GC_TIMES,\n DEFAULT_AUTH_TOKEN_TIMEOUT,\n calculateRetryDelay,\n shouldRetry,\n HttpError,\n} from './shared-types.js';\nimport type { ApiPlatformClientOptions } from './shared-types.js';\n\n// Auth query keys - shared for token management across clients\nexport const authQueryKeys = {\n bearerToken: (): QueryKey => ['auth', 'bearerToken'],\n} as const;\n\nexport type { ApiPlatformClientOptions };\n\n/**\n * Internal fetch options for HTTP requests.\n */\nexport type InternalFetchOptions = {\n signal?: AbortSignal;\n params?: Record<\n string,\n string | string[] | number | number[] | boolean | undefined\n >;\n};\n\n/**\n * Base API Client with shared HTTP and caching functionality.\n * Extended by all specific API clients.\n */\nexport class BaseApiClient {\n protected readonly clientProduct: string;\n\n protected readonly clientVersion?: string;\n\n protected readonly getBearerToken?: () => Promise<string | undefined>;\n\n protected readonly authTokenTimeout: number;\n\n readonly #queryClientInstance: QueryClient;\n\n /**\n * Get the underlying QueryClient instance.\n * Exposed for cache management operations.\n *\n * @returns The QueryClient instance.\n */\n get queryClient(): QueryClient {\n return this.#queryClientInstance;\n }\n\n /**\n * Invalidate the cached auth token.\n * Call this when the user logs out or the token expires.\n *\n * Uses resetQueries() instead of invalidateQueries() to completely remove\n * the cached value, ensuring the next request fetches a fresh token immediately.\n */\n async invalidateAuthToken(): Promise<void> {\n await this.#queryClientInstance.resetQueries({\n queryKey: authQueryKeys.bearerToken(),\n });\n }\n\n constructor(options: ApiPlatformClientOptions) {\n this.clientProduct = options.clientProduct;\n this.clientVersion = options.clientVersion;\n this.getBearerToken = options.getBearerToken;\n this.authTokenTimeout =\n options.authTokenTimeout ?? DEFAULT_AUTH_TOKEN_TIMEOUT;\n\n this.#queryClientInstance =\n options.queryClient ??\n new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: STALE_TIMES.DEFAULT,\n gcTime: GC_TIMES.DEFAULT,\n retry: shouldRetry,\n retryDelay: calculateRetryDelay,\n refetchOnWindowFocus: false,\n networkMode: 'always',\n },\n },\n });\n }\n\n /**\n * Resolve the bearer token, giving up after `authTokenTimeout` so that a slow\n * token provider does not delay the request. When the wait times out the\n * request goes out unauthenticated (lower rate limit) while the in-flight\n * `fetchQuery` keeps resolving `getBearerToken` for later requests.\n *\n * @returns The bearer token, or undefined if unavailable in time.\n */\n async #fetchBearerToken(): Promise<string | undefined> {\n const { getBearerToken } = this;\n if (!getBearerToken) {\n return undefined;\n }\n\n // fetchQuery de-duplicates concurrent callers. staleTime is 0 so we do not\n // cache the JWT here — AuthenticationController already owns token lifetime.\n const tokenPromise = this.#queryClientInstance\n .fetchQuery({\n queryKey: authQueryKeys.bearerToken(),\n queryFn: async () => {\n const result = await getBearerToken();\n // Throw if no token - prevents caching null/undefined\n // so subsequent requests can retry (e.g., after user logs in)\n if (!result) {\n throw new Error('No bearer token available');\n }\n return result;\n },\n staleTime: 0,\n retry: false, // Don't retry auth failures\n })\n .catch(() => undefined);\n\n if (this.authTokenTimeout <= 0) {\n return await tokenPromise;\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<undefined>((resolve) => {\n timeoutId = setTimeout(() => resolve(undefined), this.authTokenTimeout);\n });\n\n try {\n return await Promise.race([tokenPromise, timeoutPromise]);\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Internal HTTP fetch method with authentication and error handling.\n *\n * @param baseUrl - The base URL for the API.\n * @param path - The API endpoint path.\n * @param options - Optional fetch configuration.\n * @returns The parsed JSON response.\n */\n protected async fetch<ResponseType>(\n baseUrl: string,\n path: string,\n options?: InternalFetchOptions,\n ): Promise<ResponseType> {\n const url = new URL(path, baseUrl);\n\n if (options?.params) {\n for (const [key, value] of Object.entries(options.params)) {\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n // Convert array values (including number[]) to comma-separated string\n url.searchParams.set(key, value.map(String).join(','));\n } else {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-metamask-clientproduct': this.clientProduct,\n };\n\n if (this.clientVersion) {\n headers['x-metamask-clientversion'] = this.clientVersion;\n }\n\n const token = await this.#fetchBearerToken();\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n const response = await fetch(url.toString(), {\n method: 'GET',\n headers,\n signal: options?.signal,\n });\n\n if (!response.ok) {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n // Response body is not JSON or is empty, leave body as undefined\n }\n throw new HttpError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n response.statusText,\n url.toString(),\n body,\n );\n }\n\n return response.json() as Promise<ResponseType>;\n }\n}\n\n// Re-export constants for use by API clients\nexport { API_URLS, STALE_TIMES, GC_TIMES, HttpError };\n"]}
|
package/dist/api/index.cjs
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
* Re-exports all types and clients from the API folder.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.createApiPlatformClient = exports.ApiPlatformClient = exports.BaseApiClient = exports.TokensApiClient = exports.TokenApiClient = exports.PricesApiClient = exports.V6_DEFI_POSITION_TYPES = exports.AccountsApiClient = exports.HttpError = exports.shouldRetry = exports.getQueryOptionsOverrides = exports.calculateRetryDelay = exports.RETRY_CONFIG = exports.GC_TIMES = exports.STALE_TIMES = exports.API_URLS = void 0;
|
|
7
|
+
exports.createApiPlatformClient = exports.ApiPlatformClient = exports.BaseApiClient = exports.TokensApiClient = exports.TokenApiClient = exports.PricesApiClient = exports.V6_DEFI_POSITION_TYPES = exports.AccountsApiClient = exports.HttpError = exports.shouldRetry = exports.getQueryOptionsOverrides = exports.calculateRetryDelay = exports.RETRY_CONFIG = exports.DEFAULT_AUTH_TOKEN_TIMEOUT = exports.GC_TIMES = exports.STALE_TIMES = exports.API_URLS = void 0;
|
|
8
8
|
var shared_types_js_1 = require("./shared-types.cjs");
|
|
9
9
|
Object.defineProperty(exports, "API_URLS", { enumerable: true, get: function () { return shared_types_js_1.API_URLS; } });
|
|
10
10
|
Object.defineProperty(exports, "STALE_TIMES", { enumerable: true, get: function () { return shared_types_js_1.STALE_TIMES; } });
|
|
11
11
|
Object.defineProperty(exports, "GC_TIMES", { enumerable: true, get: function () { return shared_types_js_1.GC_TIMES; } });
|
|
12
|
+
Object.defineProperty(exports, "DEFAULT_AUTH_TOKEN_TIMEOUT", { enumerable: true, get: function () { return shared_types_js_1.DEFAULT_AUTH_TOKEN_TIMEOUT; } });
|
|
12
13
|
Object.defineProperty(exports, "RETRY_CONFIG", { enumerable: true, get: function () { return shared_types_js_1.RETRY_CONFIG; } });
|
|
13
14
|
Object.defineProperty(exports, "calculateRetryDelay", { enumerable: true, get: function () { return shared_types_js_1.calculateRetryDelay; } });
|
|
14
15
|
Object.defineProperty(exports, "getQueryOptionsOverrides", { enumerable: true, get: function () { return shared_types_js_1.getQueryOptionsOverrides; } });
|
package/dist/api/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAUH,
|
|
1
|
+
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAUH,sDAU2B;AATzB,2GAAA,QAAQ,OAAA;AACR,8GAAA,WAAW,OAAA;AACX,2GAAA,QAAQ,OAAA;AACR,6HAAA,0BAA0B,OAAA;AAC1B,+GAAA,YAAY,OAAA;AACZ,sHAAA,mBAAmB,OAAA;AACnB,2HAAA,wBAAwB,OAAA;AACxB,8GAAA,WAAW,OAAA;AACX,4GAAA,SAAS,OAAA;AAGX,eAAe;AACf,iDAAgF;AAAvE,6GAAA,iBAAiB,OAAA;AAAE,kHAAA,sBAAsB,OAAA;AA2BlD,aAAa;AACb,+CAAoD;AAA3C,2GAAA,eAAe,OAAA;AAWxB,YAAY;AACZ,8CAAkD;AAAzC,0GAAA,cAAc,OAAA;AAavB,aAAa;AACb,+CAAoD;AAA3C,2GAAA,eAAe,OAAA;AAOxB,cAAc;AACd,oDAAiD;AAAxC,+GAAA,aAAa,OAAA;AAGtB,uCAAuC;AACvC,gEAGgC;AAF9B,yHAAA,iBAAiB,OAAA;AACjB,+HAAA,uBAAuB,OAAA","sourcesContent":["/**\n * API barrel export.\n * Re-exports all types and clients from the API folder.\n */\n\n// Shared types and utilities\nexport type {\n PageInfo,\n SupportedCurrency,\n MarketDataDetails,\n ApiPlatformClientOptions,\n FetchOptions,\n} from './shared-types.js';\nexport {\n API_URLS,\n STALE_TIMES,\n GC_TIMES,\n DEFAULT_AUTH_TOKEN_TIMEOUT,\n RETRY_CONFIG,\n calculateRetryDelay,\n getQueryOptionsOverrides,\n shouldRetry,\n HttpError,\n} from './shared-types.js';\n\n// Accounts API\nexport { AccountsApiClient, V6_DEFI_POSITION_TYPES } from './accounts/index.js';\nexport type {\n V5BalanceItem,\n V5BalancesResponse,\n V2BalanceItem,\n V2BalancesResponse,\n V4BalancesResponse,\n V6VsCurrency,\n V6DeFiPositionType,\n V6BalanceMetadata,\n V6TokenMetadata,\n V6BalanceItem,\n V6BalancesResponse,\n V1SupportedNetworksResponse,\n V2SupportedNetworksResponse,\n V2ActiveNetworksResponse,\n V1TransactionByHashResponse,\n V1AccountTransactionsResponse,\n V4MultiAccountTransactionsResponse,\n ValueTransfer,\n V1AccountRelationshipResult,\n NftItem,\n V2NftsResponse,\n TokenDiscoveryItem,\n V2TokensResponse,\n} from './accounts/index.js';\n\n// Prices API\nexport { PricesApiClient } from './prices/index.js';\nexport type {\n V3SpotPricesResponse,\n CoinGeckoSpotPrice,\n ExchangeRateInfo,\n V1ExchangeRatesResponse,\n PriceSupportedNetworksResponse,\n V1HistoricalPricesResponse,\n V3HistoricalPricesResponse,\n} from './prices/index.js';\n\n// Token API\nexport { TokenApiClient } from './token/index.js';\nexport type {\n TokenMetadata,\n V1TokenDescriptionResponse,\n NetworkInfo,\n TopAsset,\n TrendingSortBy,\n TrendingToken,\n TopGainersSortOption,\n TrendingSortOption,\n V1SuggestedOccurrenceFloorsResponse,\n} from './token/index.js';\n\n// Tokens API\nexport { TokensApiClient } from './tokens/index.js';\nexport type {\n V1TokenSupportedNetworksResponse,\n V2TokenSupportedNetworksResponse,\n V3AssetResponse,\n} from './tokens/index.js';\n\n// Base client\nexport { BaseApiClient } from './base-client.js';\nexport type { InternalFetchOptions } from './base-client.js';\n\n// API Platform Client (unified client)\nexport {\n ApiPlatformClient,\n createApiPlatformClient,\n} from './ApiPlatformClient.js';\n"]}
|
package/dist/api/index.d.cts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Re-exports all types and clients from the API folder.
|
|
4
4
|
*/
|
|
5
5
|
export type { PageInfo, SupportedCurrency, MarketDataDetails, ApiPlatformClientOptions, FetchOptions, } from "./shared-types.cjs";
|
|
6
|
-
export { API_URLS, STALE_TIMES, GC_TIMES, RETRY_CONFIG, calculateRetryDelay, getQueryOptionsOverrides, shouldRetry, HttpError, } from "./shared-types.cjs";
|
|
6
|
+
export { API_URLS, STALE_TIMES, GC_TIMES, DEFAULT_AUTH_TOKEN_TIMEOUT, RETRY_CONFIG, calculateRetryDelay, getQueryOptionsOverrides, shouldRetry, HttpError, } from "./shared-types.cjs";
|
|
7
7
|
export { AccountsApiClient, V6_DEFI_POSITION_TYPES } from "./accounts/index.cjs";
|
|
8
8
|
export type { V5BalanceItem, V5BalancesResponse, V2BalanceItem, V2BalancesResponse, V4BalancesResponse, V6VsCurrency, V6DeFiPositionType, V6BalanceMetadata, V6TokenMetadata, V6BalanceItem, V6BalancesResponse, V1SupportedNetworksResponse, V2SupportedNetworksResponse, V2ActiveNetworksResponse, V1TransactionByHashResponse, V1AccountTransactionsResponse, V4MultiAccountTransactionsResponse, ValueTransfer, V1AccountRelationshipResult, NftItem, V2NftsResponse, TokenDiscoveryItem, V2TokensResponse, } from "./accounts/index.cjs";
|
|
9
9
|
export { PricesApiClient } from "./prices/index.cjs";
|
package/dist/api/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EACV,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,GACb,2BAA0B;AAC3B,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,SAAS,GACV,2BAA0B;AAG3B,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,6BAA4B;AAChF,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,2BAA2B,EAC3B,2BAA2B,EAC3B,wBAAwB,EACxB,2BAA2B,EAC3B,6BAA6B,EAC7B,kCAAkC,EAClC,aAAa,EACb,2BAA2B,EAC3B,OAAO,EACP,cAAc,EACd,kBAAkB,EAClB,gBAAgB,GACjB,6BAA4B;AAG7B,OAAO,EAAE,eAAe,EAAE,2BAA0B;AACpD,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,8BAA8B,EAC9B,0BAA0B,EAC1B,0BAA0B,GAC3B,2BAA0B;AAG3B,OAAO,EAAE,cAAc,EAAE,0BAAyB;AAClD,YAAY,EACV,aAAa,EACb,0BAA0B,EAC1B,WAAW,EACX,QAAQ,EACR,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,mCAAmC,GACpC,0BAAyB;AAG1B,OAAO,EAAE,eAAe,EAAE,2BAA0B;AACpD,YAAY,EACV,gCAAgC,EAChC,gCAAgC,EAChC,eAAe,GAChB,2BAA0B;AAG3B,OAAO,EAAE,aAAa,EAAE,0BAAyB;AACjD,YAAY,EAAE,oBAAoB,EAAE,0BAAyB;AAG7D,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,gCAA+B"}
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EACV,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,GACb,2BAA0B;AAC3B,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,0BAA0B,EAC1B,YAAY,EACZ,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,SAAS,GACV,2BAA0B;AAG3B,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,6BAA4B;AAChF,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,2BAA2B,EAC3B,2BAA2B,EAC3B,wBAAwB,EACxB,2BAA2B,EAC3B,6BAA6B,EAC7B,kCAAkC,EAClC,aAAa,EACb,2BAA2B,EAC3B,OAAO,EACP,cAAc,EACd,kBAAkB,EAClB,gBAAgB,GACjB,6BAA4B;AAG7B,OAAO,EAAE,eAAe,EAAE,2BAA0B;AACpD,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,8BAA8B,EAC9B,0BAA0B,EAC1B,0BAA0B,GAC3B,2BAA0B;AAG3B,OAAO,EAAE,cAAc,EAAE,0BAAyB;AAClD,YAAY,EACV,aAAa,EACb,0BAA0B,EAC1B,WAAW,EACX,QAAQ,EACR,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,mCAAmC,GACpC,0BAAyB;AAG1B,OAAO,EAAE,eAAe,EAAE,2BAA0B;AACpD,YAAY,EACV,gCAAgC,EAChC,gCAAgC,EAChC,eAAe,GAChB,2BAA0B;AAG3B,OAAO,EAAE,aAAa,EAAE,0BAAyB;AACjD,YAAY,EAAE,oBAAoB,EAAE,0BAAyB;AAG7D,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,gCAA+B"}
|
package/dist/api/index.d.mts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Re-exports all types and clients from the API folder.
|
|
4
4
|
*/
|
|
5
5
|
export type { PageInfo, SupportedCurrency, MarketDataDetails, ApiPlatformClientOptions, FetchOptions, } from "./shared-types.mjs";
|
|
6
|
-
export { API_URLS, STALE_TIMES, GC_TIMES, RETRY_CONFIG, calculateRetryDelay, getQueryOptionsOverrides, shouldRetry, HttpError, } from "./shared-types.mjs";
|
|
6
|
+
export { API_URLS, STALE_TIMES, GC_TIMES, DEFAULT_AUTH_TOKEN_TIMEOUT, RETRY_CONFIG, calculateRetryDelay, getQueryOptionsOverrides, shouldRetry, HttpError, } from "./shared-types.mjs";
|
|
7
7
|
export { AccountsApiClient, V6_DEFI_POSITION_TYPES } from "./accounts/index.mjs";
|
|
8
8
|
export type { V5BalanceItem, V5BalancesResponse, V2BalanceItem, V2BalancesResponse, V4BalancesResponse, V6VsCurrency, V6DeFiPositionType, V6BalanceMetadata, V6TokenMetadata, V6BalanceItem, V6BalancesResponse, V1SupportedNetworksResponse, V2SupportedNetworksResponse, V2ActiveNetworksResponse, V1TransactionByHashResponse, V1AccountTransactionsResponse, V4MultiAccountTransactionsResponse, ValueTransfer, V1AccountRelationshipResult, NftItem, V2NftsResponse, TokenDiscoveryItem, V2TokensResponse, } from "./accounts/index.mjs";
|
|
9
9
|
export { PricesApiClient } from "./prices/index.mjs";
|
package/dist/api/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EACV,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,GACb,2BAA0B;AAC3B,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,SAAS,GACV,2BAA0B;AAG3B,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,6BAA4B;AAChF,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,2BAA2B,EAC3B,2BAA2B,EAC3B,wBAAwB,EACxB,2BAA2B,EAC3B,6BAA6B,EAC7B,kCAAkC,EAClC,aAAa,EACb,2BAA2B,EAC3B,OAAO,EACP,cAAc,EACd,kBAAkB,EAClB,gBAAgB,GACjB,6BAA4B;AAG7B,OAAO,EAAE,eAAe,EAAE,2BAA0B;AACpD,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,8BAA8B,EAC9B,0BAA0B,EAC1B,0BAA0B,GAC3B,2BAA0B;AAG3B,OAAO,EAAE,cAAc,EAAE,0BAAyB;AAClD,YAAY,EACV,aAAa,EACb,0BAA0B,EAC1B,WAAW,EACX,QAAQ,EACR,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,mCAAmC,GACpC,0BAAyB;AAG1B,OAAO,EAAE,eAAe,EAAE,2BAA0B;AACpD,YAAY,EACV,gCAAgC,EAChC,gCAAgC,EAChC,eAAe,GAChB,2BAA0B;AAG3B,OAAO,EAAE,aAAa,EAAE,0BAAyB;AACjD,YAAY,EAAE,oBAAoB,EAAE,0BAAyB;AAG7D,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,gCAA+B"}
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EACV,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,GACb,2BAA0B;AAC3B,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,0BAA0B,EAC1B,YAAY,EACZ,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,SAAS,GACV,2BAA0B;AAG3B,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,6BAA4B;AAChF,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,2BAA2B,EAC3B,2BAA2B,EAC3B,wBAAwB,EACxB,2BAA2B,EAC3B,6BAA6B,EAC7B,kCAAkC,EAClC,aAAa,EACb,2BAA2B,EAC3B,OAAO,EACP,cAAc,EACd,kBAAkB,EAClB,gBAAgB,GACjB,6BAA4B;AAG7B,OAAO,EAAE,eAAe,EAAE,2BAA0B;AACpD,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,8BAA8B,EAC9B,0BAA0B,EAC1B,0BAA0B,GAC3B,2BAA0B;AAG3B,OAAO,EAAE,cAAc,EAAE,0BAAyB;AAClD,YAAY,EACV,aAAa,EACb,0BAA0B,EAC1B,WAAW,EACX,QAAQ,EACR,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,mCAAmC,GACpC,0BAAyB;AAG1B,OAAO,EAAE,eAAe,EAAE,2BAA0B;AACpD,YAAY,EACV,gCAAgC,EAChC,gCAAgC,EAChC,eAAe,GAChB,2BAA0B;AAG3B,OAAO,EAAE,aAAa,EAAE,0BAAyB;AACjD,YAAY,EAAE,oBAAoB,EAAE,0BAAyB;AAG7D,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,gCAA+B"}
|
package/dist/api/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* API barrel export.
|
|
3
3
|
* Re-exports all types and clients from the API folder.
|
|
4
4
|
*/
|
|
5
|
-
export { API_URLS, STALE_TIMES, GC_TIMES, RETRY_CONFIG, calculateRetryDelay, getQueryOptionsOverrides, shouldRetry, HttpError } from "./shared-types.mjs";
|
|
5
|
+
export { API_URLS, STALE_TIMES, GC_TIMES, DEFAULT_AUTH_TOKEN_TIMEOUT, RETRY_CONFIG, calculateRetryDelay, getQueryOptionsOverrides, shouldRetry, HttpError } from "./shared-types.mjs";
|
|
6
6
|
// Accounts API
|
|
7
7
|
export { AccountsApiClient, V6_DEFI_POSITION_TYPES } from "./accounts/index.mjs";
|
|
8
8
|
// Prices API
|
package/dist/api/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,SAAS,EACV,2BAA0B;AAE3B,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,6BAA4B;AA2BhF,aAAa;AACb,OAAO,EAAE,eAAe,EAAE,2BAA0B;AAWpD,YAAY;AACZ,OAAO,EAAE,cAAc,EAAE,0BAAyB;AAalD,aAAa;AACb,OAAO,EAAE,eAAe,EAAE,2BAA0B;AAOpD,cAAc;AACd,OAAO,EAAE,aAAa,EAAE,0BAAyB;AAGjD,uCAAuC;AACvC,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACxB,gCAA+B","sourcesContent":["/**\n * API barrel export.\n * Re-exports all types and clients from the API folder.\n */\n\n// Shared types and utilities\nexport type {\n PageInfo,\n SupportedCurrency,\n MarketDataDetails,\n ApiPlatformClientOptions,\n FetchOptions,\n} from './shared-types.js';\nexport {\n API_URLS,\n STALE_TIMES,\n GC_TIMES,\n RETRY_CONFIG,\n calculateRetryDelay,\n getQueryOptionsOverrides,\n shouldRetry,\n HttpError,\n} from './shared-types.js';\n\n// Accounts API\nexport { AccountsApiClient, V6_DEFI_POSITION_TYPES } from './accounts/index.js';\nexport type {\n V5BalanceItem,\n V5BalancesResponse,\n V2BalanceItem,\n V2BalancesResponse,\n V4BalancesResponse,\n V6VsCurrency,\n V6DeFiPositionType,\n V6BalanceMetadata,\n V6TokenMetadata,\n V6BalanceItem,\n V6BalancesResponse,\n V1SupportedNetworksResponse,\n V2SupportedNetworksResponse,\n V2ActiveNetworksResponse,\n V1TransactionByHashResponse,\n V1AccountTransactionsResponse,\n V4MultiAccountTransactionsResponse,\n ValueTransfer,\n V1AccountRelationshipResult,\n NftItem,\n V2NftsResponse,\n TokenDiscoveryItem,\n V2TokensResponse,\n} from './accounts/index.js';\n\n// Prices API\nexport { PricesApiClient } from './prices/index.js';\nexport type {\n V3SpotPricesResponse,\n CoinGeckoSpotPrice,\n ExchangeRateInfo,\n V1ExchangeRatesResponse,\n PriceSupportedNetworksResponse,\n V1HistoricalPricesResponse,\n V3HistoricalPricesResponse,\n} from './prices/index.js';\n\n// Token API\nexport { TokenApiClient } from './token/index.js';\nexport type {\n TokenMetadata,\n V1TokenDescriptionResponse,\n NetworkInfo,\n TopAsset,\n TrendingSortBy,\n TrendingToken,\n TopGainersSortOption,\n TrendingSortOption,\n V1SuggestedOccurrenceFloorsResponse,\n} from './token/index.js';\n\n// Tokens API\nexport { TokensApiClient } from './tokens/index.js';\nexport type {\n V1TokenSupportedNetworksResponse,\n V2TokenSupportedNetworksResponse,\n V3AssetResponse,\n} from './tokens/index.js';\n\n// Base client\nexport { BaseApiClient } from './base-client.js';\nexport type { InternalFetchOptions } from './base-client.js';\n\n// API Platform Client (unified client)\nexport {\n ApiPlatformClient,\n createApiPlatformClient,\n} from './ApiPlatformClient.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,0BAA0B,EAC1B,YAAY,EACZ,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,SAAS,EACV,2BAA0B;AAE3B,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,6BAA4B;AA2BhF,aAAa;AACb,OAAO,EAAE,eAAe,EAAE,2BAA0B;AAWpD,YAAY;AACZ,OAAO,EAAE,cAAc,EAAE,0BAAyB;AAalD,aAAa;AACb,OAAO,EAAE,eAAe,EAAE,2BAA0B;AAOpD,cAAc;AACd,OAAO,EAAE,aAAa,EAAE,0BAAyB;AAGjD,uCAAuC;AACvC,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACxB,gCAA+B","sourcesContent":["/**\n * API barrel export.\n * Re-exports all types and clients from the API folder.\n */\n\n// Shared types and utilities\nexport type {\n PageInfo,\n SupportedCurrency,\n MarketDataDetails,\n ApiPlatformClientOptions,\n FetchOptions,\n} from './shared-types.js';\nexport {\n API_URLS,\n STALE_TIMES,\n GC_TIMES,\n DEFAULT_AUTH_TOKEN_TIMEOUT,\n RETRY_CONFIG,\n calculateRetryDelay,\n getQueryOptionsOverrides,\n shouldRetry,\n HttpError,\n} from './shared-types.js';\n\n// Accounts API\nexport { AccountsApiClient, V6_DEFI_POSITION_TYPES } from './accounts/index.js';\nexport type {\n V5BalanceItem,\n V5BalancesResponse,\n V2BalanceItem,\n V2BalancesResponse,\n V4BalancesResponse,\n V6VsCurrency,\n V6DeFiPositionType,\n V6BalanceMetadata,\n V6TokenMetadata,\n V6BalanceItem,\n V6BalancesResponse,\n V1SupportedNetworksResponse,\n V2SupportedNetworksResponse,\n V2ActiveNetworksResponse,\n V1TransactionByHashResponse,\n V1AccountTransactionsResponse,\n V4MultiAccountTransactionsResponse,\n ValueTransfer,\n V1AccountRelationshipResult,\n NftItem,\n V2NftsResponse,\n TokenDiscoveryItem,\n V2TokensResponse,\n} from './accounts/index.js';\n\n// Prices API\nexport { PricesApiClient } from './prices/index.js';\nexport type {\n V3SpotPricesResponse,\n CoinGeckoSpotPrice,\n ExchangeRateInfo,\n V1ExchangeRatesResponse,\n PriceSupportedNetworksResponse,\n V1HistoricalPricesResponse,\n V3HistoricalPricesResponse,\n} from './prices/index.js';\n\n// Token API\nexport { TokenApiClient } from './token/index.js';\nexport type {\n TokenMetadata,\n V1TokenDescriptionResponse,\n NetworkInfo,\n TopAsset,\n TrendingSortBy,\n TrendingToken,\n TopGainersSortOption,\n TrendingSortOption,\n V1SuggestedOccurrenceFloorsResponse,\n} from './token/index.js';\n\n// Tokens API\nexport { TokensApiClient } from './tokens/index.js';\nexport type {\n V1TokenSupportedNetworksResponse,\n V2TokenSupportedNetworksResponse,\n V3AssetResponse,\n} from './tokens/index.js';\n\n// Base client\nexport { BaseApiClient } from './base-client.js';\nexport type { InternalFetchOptions } from './base-client.js';\n\n// API Platform Client (unified client)\nexport {\n ApiPlatformClient,\n createApiPlatformClient,\n} from './ApiPlatformClient.js';\n"]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Shared types, constants, and utilities for the API Platform Client.
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.HttpError = exports.shouldRetry = exports.calculateRetryDelay = exports.RETRY_CONFIG = exports.GC_TIMES = exports.STALE_TIMES = exports.API_URLS = exports.getQueryOptionsOverrides = void 0;
|
|
6
|
+
exports.HttpError = exports.shouldRetry = exports.calculateRetryDelay = exports.RETRY_CONFIG = exports.GC_TIMES = exports.DEFAULT_AUTH_TOKEN_TIMEOUT = exports.STALE_TIMES = exports.API_URLS = exports.getQueryOptionsOverrides = void 0;
|
|
7
7
|
/**
|
|
8
8
|
* Returns options with queryKey and queryFn omitted, for merging into
|
|
9
9
|
* get*QueryOptions return values without overwriting the client's queryKey/queryFn.
|
|
@@ -33,7 +33,6 @@ exports.API_URLS = {
|
|
|
33
33
|
};
|
|
34
34
|
/** Stale times for different data types (ms) */
|
|
35
35
|
exports.STALE_TIMES = {
|
|
36
|
-
AUTH_TOKEN: 5 * 60 * 1000, // 5 minutes - cache the auth token
|
|
37
36
|
PRICES: 30 * 1000, // 30 seconds
|
|
38
37
|
BALANCES: 60 * 1000, // 1 minute
|
|
39
38
|
NETWORKS: 10 * 60 * 1000, // 10 minutes
|
|
@@ -45,6 +44,11 @@ exports.STALE_TIMES = {
|
|
|
45
44
|
TRANSACTIONS: 30 * 1000, // 30 seconds
|
|
46
45
|
DEFAULT: 30 * 1000, // 30 seconds
|
|
47
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* Default max time (ms) to wait for the bearer token before falling back to an
|
|
49
|
+
* unauthenticated request.
|
|
50
|
+
*/
|
|
51
|
+
exports.DEFAULT_AUTH_TOKEN_TIMEOUT = 500;
|
|
48
52
|
/** Garbage collection times (ms) */
|
|
49
53
|
exports.GC_TIMES = {
|
|
50
54
|
DEFAULT: 5 * 60 * 1000, // 5 minutes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-types.cjs","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared types, constants, and utilities for the API Platform Client.\n */\n\nimport type { FetchQueryOptions, QueryClient } from '@tanstack/query-core';\n\n// ============================================================================\n// SHARED TYPES\n// ============================================================================\n\n/**\n * Pagination info for paginated responses\n */\nexport type PageInfo = {\n count: number;\n hasNextPage: boolean;\n cursor?: string;\n};\n\n/**\n * Supported currencies for Price API\n */\nexport type SupportedCurrency =\n // Crypto\n | 'btc'\n | 'eth'\n | 'ltc'\n | 'bch'\n | 'bnb'\n | 'eos'\n | 'xrp'\n | 'xlm'\n | 'link'\n | 'dot'\n | 'yfi'\n // Fiat\n | 'usd'\n | 'aed'\n | 'ars'\n | 'aud'\n | 'bdt'\n | 'bhd'\n | 'bmd'\n | 'brl'\n | 'cad'\n | 'chf'\n | 'clp'\n | 'cny'\n | 'czk'\n | 'dkk'\n | 'eur'\n | 'gbp'\n | 'gel'\n | 'hkd'\n | 'huf'\n | 'idr'\n | 'ils'\n | 'inr'\n | 'jpy'\n | 'krw'\n | 'kwd'\n | 'lkr'\n | 'mmk'\n | 'mxn'\n | 'myr'\n | 'ngn'\n | 'nok'\n | 'nzd'\n | 'php'\n | 'pkr'\n | 'pln'\n | 'rub'\n | 'sar'\n | 'sek'\n | 'sgd'\n | 'thb'\n | 'try'\n | 'twd'\n | 'uah'\n | 'vef'\n | 'vnd'\n | 'zar';\n\n/**\n * Market data details from Price API spot-prices endpoint\n */\nexport type MarketDataDetails = {\n /** Current price in the requested currency */\n price: number;\n /** Currency code (e.g., 'ETH', 'USD') */\n currency: string;\n /** 24h price change amount */\n priceChange1d: number;\n /** 24h price change percentage */\n pricePercentChange1d: number;\n /** 1h price change percentage */\n pricePercentChange1h: number;\n /** 7d price change percentage */\n pricePercentChange7d: number;\n /** 14d price change percentage */\n pricePercentChange14d: number;\n /** 30d price change percentage */\n pricePercentChange30d: number;\n /** 200d price change percentage */\n pricePercentChange200d: number;\n /** 1y price change percentage */\n pricePercentChange1y: number;\n /** Market capitalization */\n marketCap: number;\n /** Market cap 24h change percentage */\n marketCapPercentChange1d: number;\n /** All-time high price */\n allTimeHigh: number;\n /** All-time low price */\n allTimeLow: number;\n /** 24h high price */\n high1d: number;\n /** 24h low price */\n low1d: number;\n /** Total trading volume */\n totalVolume: number;\n /** Circulating supply */\n circulatingSupply: number;\n /** Diluted market cap */\n dilutedMarketCap: number;\n};\n\n// ============================================================================\n// CLIENT OPTIONS\n// ============================================================================\n\nexport type ApiPlatformClientOptions = {\n /** Client product identifier (e.g., 'metamask-extension') */\n clientProduct: string;\n /** Optional client version */\n clientVersion?: string;\n /** Function to get bearer token for authenticated requests */\n getBearerToken?: () => Promise<string | undefined>;\n /** Optional custom QueryClient instance */\n queryClient?: QueryClient;\n};\n\n/**\n * Options for API fetch and query methods.\n * Extends TanStack Query options (e.g. select, initialPageParam, retry) so callers\n * can pass them through to useQuery / useInfiniteQuery. queryKey and queryFn are\n * always set by the client and cannot be overridden.\n * staleTime and gcTime are explicitly number (not function) so that client defaults apply without type conflicts.\n */\nexport type FetchOptions = {\n /** Custom stale time (ms). */\n staleTime?: number;\n /** Custom GC time (ms). */\n gcTime?: number;\n /**\n * When true, bypass caching for this request: the client-side query cache is\n * skipped (stale time defaults to 0) and, on endpoints that support it, a\n * random `bypassServerCache` query param is appended so server-side HTTP caches\n * (keyed on the full URL) miss. Use sparingly — only when a hard refresh is\n * required, e.g. right after a transaction confirms.\n */\n bypassServerCache?: boolean;\n} & Partial<\n Omit<\n FetchQueryOptions<unknown, Error, unknown>,\n 'queryKey' | 'queryFn' | 'staleTime' | 'gcTime'\n >\n> & {\n /** Allowed for infinite query options (e.g. useInfiniteQuery). */\n initialPageParam?: unknown;\n };\n\n/**\n * Returns options with queryKey and queryFn omitted, for merging into\n * get*QueryOptions return values without overwriting the client's queryKey/queryFn.\n * Return type is intentionally loose so that spreading into FetchQueryOptions<T>\n * does not conflict with T-specific option types (e.g. select, staleTime).\n *\n * @param options - Optional FetchOptions from the caller.\n * @returns Options safe to spread into query options, or undefined.\n */\nexport function getQueryOptionsOverrides(\n options?: FetchOptions,\n): Record<string, unknown> | undefined {\n if (options === null || options === undefined) {\n return undefined;\n }\n const {\n queryKey: _qk,\n queryFn: _qf,\n bypassServerCache: _bc,\n ...rest\n } = options as FetchOptions & {\n queryKey?: unknown;\n queryFn?: unknown;\n };\n return rest as Record<string, unknown>;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\n/** API Base URLs */\nexport const API_URLS = {\n ACCOUNTS: 'https://accounts.api.cx.metamask.io',\n PRICES: 'https://price.api.cx.metamask.io',\n TOKEN: 'https://token.api.cx.metamask.io',\n TOKENS: 'https://tokens.api.cx.metamask.io',\n} as const;\n\n/** Stale times for different data types (ms) */\nexport const STALE_TIMES = {\n AUTH_TOKEN: 5 * 60 * 1000, // 5 minutes - cache the auth token\n PRICES: 30 * 1000, // 30 seconds\n BALANCES: 60 * 1000, // 1 minute\n NETWORKS: 10 * 60 * 1000, // 10 minutes\n SUPPORTED_NETWORKS: 30 * 60 * 1000, // 30 minutes\n TOKEN_METADATA: 5 * 60 * 1000, // 5 minutes\n TOKEN_LIST: 10 * 60 * 1000, // 10 minutes\n EXCHANGE_RATES: 5 * 60 * 1000, // 5 minutes\n TRENDING: 2 * 60 * 1000, // 2 minutes\n TRANSACTIONS: 30 * 1000, // 30 seconds\n DEFAULT: 30 * 1000, // 30 seconds\n} as const;\n\n/** Garbage collection times (ms) */\nexport const GC_TIMES = {\n DEFAULT: 5 * 60 * 1000, // 5 minutes\n EXTENDED: 30 * 60 * 1000, // 30 minutes\n SHORT: 2 * 60 * 1000, // 2 minutes\n} as const;\n\n/** Retry configuration */\nexport const RETRY_CONFIG = {\n MAX_RETRIES: 3,\n BASE_DELAY: 1000,\n MAX_DELAY: 5_000,\n} as const;\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Calculate retry delay with exponential backoff and jitter.\n *\n * @param attemptIndex - The current retry attempt (0-indexed).\n * @returns The delay in milliseconds before the next retry.\n */\nexport function calculateRetryDelay(attemptIndex: number): number {\n const delay = Math.min(\n RETRY_CONFIG.BASE_DELAY * 2 ** attemptIndex,\n RETRY_CONFIG.MAX_DELAY,\n );\n return delay / 2 + Math.random() * (delay / 2);\n}\n\n/**\n * Determine if a failed request should be retried.\n *\n * @param failureCount - The number of failures so far (1 = first failure).\n * @param error - The error from the failed request.\n * @returns True if the request should be retried, false otherwise.\n */\nexport function shouldRetry(failureCount: number, error: unknown): boolean {\n // Allow up to MAX_RETRIES retries (e.g., MAX_RETRIES=3 means 4 total attempts)\n if (failureCount > RETRY_CONFIG.MAX_RETRIES) {\n return false;\n }\n\n if (error instanceof Error && 'status' in error) {\n const { status } = error as { status: number };\n // Don't retry 4xx except 429 (rate limit) and 408 (timeout)\n if (status >= 400 && status < 500 && status !== 429 && status !== 408) {\n return false;\n }\n }\n return true;\n}\n\n// ============================================================================\n// HTTP ERROR\n// ============================================================================\n\nexport class HttpError extends Error {\n readonly status: number;\n\n readonly statusText: string;\n\n readonly url: string;\n\n readonly body: unknown;\n\n constructor(\n message: string,\n status: number,\n statusText: string,\n url: string,\n body?: unknown,\n ) {\n super(message);\n this.name = 'HttpError';\n this.status = status;\n this.statusText = statusText;\n this.url = url;\n this.body = body;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shared-types.cjs","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared types, constants, and utilities for the API Platform Client.\n */\n\nimport type { FetchQueryOptions, QueryClient } from '@tanstack/query-core';\n\n// ============================================================================\n// SHARED TYPES\n// ============================================================================\n\n/**\n * Pagination info for paginated responses\n */\nexport type PageInfo = {\n count: number;\n hasNextPage: boolean;\n cursor?: string;\n};\n\n/**\n * Supported currencies for Price API\n */\nexport type SupportedCurrency =\n // Crypto\n | 'btc'\n | 'eth'\n | 'ltc'\n | 'bch'\n | 'bnb'\n | 'eos'\n | 'xrp'\n | 'xlm'\n | 'link'\n | 'dot'\n | 'yfi'\n // Fiat\n | 'usd'\n | 'aed'\n | 'ars'\n | 'aud'\n | 'bdt'\n | 'bhd'\n | 'bmd'\n | 'brl'\n | 'cad'\n | 'chf'\n | 'clp'\n | 'cny'\n | 'czk'\n | 'dkk'\n | 'eur'\n | 'gbp'\n | 'gel'\n | 'hkd'\n | 'huf'\n | 'idr'\n | 'ils'\n | 'inr'\n | 'jpy'\n | 'krw'\n | 'kwd'\n | 'lkr'\n | 'mmk'\n | 'mxn'\n | 'myr'\n | 'ngn'\n | 'nok'\n | 'nzd'\n | 'php'\n | 'pkr'\n | 'pln'\n | 'rub'\n | 'sar'\n | 'sek'\n | 'sgd'\n | 'thb'\n | 'try'\n | 'twd'\n | 'uah'\n | 'vef'\n | 'vnd'\n | 'zar';\n\n/**\n * Market data details from Price API spot-prices endpoint\n */\nexport type MarketDataDetails = {\n /** Current price in the requested currency */\n price: number;\n /** Currency code (e.g., 'ETH', 'USD') */\n currency: string;\n /** 24h price change amount */\n priceChange1d: number;\n /** 24h price change percentage */\n pricePercentChange1d: number;\n /** 1h price change percentage */\n pricePercentChange1h: number;\n /** 7d price change percentage */\n pricePercentChange7d: number;\n /** 14d price change percentage */\n pricePercentChange14d: number;\n /** 30d price change percentage */\n pricePercentChange30d: number;\n /** 200d price change percentage */\n pricePercentChange200d: number;\n /** 1y price change percentage */\n pricePercentChange1y: number;\n /** Market capitalization */\n marketCap: number;\n /** Market cap 24h change percentage */\n marketCapPercentChange1d: number;\n /** All-time high price */\n allTimeHigh: number;\n /** All-time low price */\n allTimeLow: number;\n /** 24h high price */\n high1d: number;\n /** 24h low price */\n low1d: number;\n /** Total trading volume */\n totalVolume: number;\n /** Circulating supply */\n circulatingSupply: number;\n /** Diluted market cap */\n dilutedMarketCap: number;\n};\n\n// ============================================================================\n// CLIENT OPTIONS\n// ============================================================================\n\nexport type ApiPlatformClientOptions = {\n /** Client product identifier (e.g., 'metamask-extension') */\n clientProduct: string;\n /** Optional client version */\n clientVersion?: string;\n /** Function to get bearer token for authenticated requests */\n getBearerToken?: () => Promise<string | undefined>;\n /**\n * Max time (ms) to wait for `getBearerToken` before sending the request\n * unauthenticated. The token keeps resolving in the background and is used by\n * later requests. Set to `0` to always wait for the token.\n * Defaults to {@link DEFAULT_AUTH_TOKEN_TIMEOUT}.\n */\n authTokenTimeout?: number;\n /** Optional custom QueryClient instance */\n queryClient?: QueryClient;\n};\n\n/**\n * Options for API fetch and query methods.\n * Extends TanStack Query options (e.g. select, initialPageParam, retry) so callers\n * can pass them through to useQuery / useInfiniteQuery. queryKey and queryFn are\n * always set by the client and cannot be overridden.\n * staleTime and gcTime are explicitly number (not function) so that client defaults apply without type conflicts.\n */\nexport type FetchOptions = {\n /** Custom stale time (ms). */\n staleTime?: number;\n /** Custom GC time (ms). */\n gcTime?: number;\n /**\n * When true, bypass caching for this request: the client-side query cache is\n * skipped (stale time defaults to 0) and, on endpoints that support it, a\n * random `bypassServerCache` query param is appended so server-side HTTP caches\n * (keyed on the full URL) miss. Use sparingly — only when a hard refresh is\n * required, e.g. right after a transaction confirms.\n */\n bypassServerCache?: boolean;\n} & Partial<\n Omit<\n FetchQueryOptions<unknown, Error, unknown>,\n 'queryKey' | 'queryFn' | 'staleTime' | 'gcTime'\n >\n> & {\n /** Allowed for infinite query options (e.g. useInfiniteQuery). */\n initialPageParam?: unknown;\n };\n\n/**\n * Returns options with queryKey and queryFn omitted, for merging into\n * get*QueryOptions return values without overwriting the client's queryKey/queryFn.\n * Return type is intentionally loose so that spreading into FetchQueryOptions<T>\n * does not conflict with T-specific option types (e.g. select, staleTime).\n *\n * @param options - Optional FetchOptions from the caller.\n * @returns Options safe to spread into query options, or undefined.\n */\nexport function getQueryOptionsOverrides(\n options?: FetchOptions,\n): Record<string, unknown> | undefined {\n if (options === null || options === undefined) {\n return undefined;\n }\n const {\n queryKey: _qk,\n queryFn: _qf,\n bypassServerCache: _bc,\n ...rest\n } = options as FetchOptions & {\n queryKey?: unknown;\n queryFn?: unknown;\n };\n return rest as Record<string, unknown>;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\n/** API Base URLs */\nexport const API_URLS = {\n ACCOUNTS: 'https://accounts.api.cx.metamask.io',\n PRICES: 'https://price.api.cx.metamask.io',\n TOKEN: 'https://token.api.cx.metamask.io',\n TOKENS: 'https://tokens.api.cx.metamask.io',\n} as const;\n\n/** Stale times for different data types (ms) */\nexport const STALE_TIMES = {\n PRICES: 30 * 1000, // 30 seconds\n BALANCES: 60 * 1000, // 1 minute\n NETWORKS: 10 * 60 * 1000, // 10 minutes\n SUPPORTED_NETWORKS: 30 * 60 * 1000, // 30 minutes\n TOKEN_METADATA: 5 * 60 * 1000, // 5 minutes\n TOKEN_LIST: 10 * 60 * 1000, // 10 minutes\n EXCHANGE_RATES: 5 * 60 * 1000, // 5 minutes\n TRENDING: 2 * 60 * 1000, // 2 minutes\n TRANSACTIONS: 30 * 1000, // 30 seconds\n DEFAULT: 30 * 1000, // 30 seconds\n} as const;\n\n/**\n * Default max time (ms) to wait for the bearer token before falling back to an\n * unauthenticated request.\n */\nexport const DEFAULT_AUTH_TOKEN_TIMEOUT = 500;\n\n/** Garbage collection times (ms) */\nexport const GC_TIMES = {\n DEFAULT: 5 * 60 * 1000, // 5 minutes\n EXTENDED: 30 * 60 * 1000, // 30 minutes\n SHORT: 2 * 60 * 1000, // 2 minutes\n} as const;\n\n/** Retry configuration */\nexport const RETRY_CONFIG = {\n MAX_RETRIES: 3,\n BASE_DELAY: 1000,\n MAX_DELAY: 5_000,\n} as const;\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Calculate retry delay with exponential backoff and jitter.\n *\n * @param attemptIndex - The current retry attempt (0-indexed).\n * @returns The delay in milliseconds before the next retry.\n */\nexport function calculateRetryDelay(attemptIndex: number): number {\n const delay = Math.min(\n RETRY_CONFIG.BASE_DELAY * 2 ** attemptIndex,\n RETRY_CONFIG.MAX_DELAY,\n );\n return delay / 2 + Math.random() * (delay / 2);\n}\n\n/**\n * Determine if a failed request should be retried.\n *\n * @param failureCount - The number of failures so far (1 = first failure).\n * @param error - The error from the failed request.\n * @returns True if the request should be retried, false otherwise.\n */\nexport function shouldRetry(failureCount: number, error: unknown): boolean {\n // Allow up to MAX_RETRIES retries (e.g., MAX_RETRIES=3 means 4 total attempts)\n if (failureCount > RETRY_CONFIG.MAX_RETRIES) {\n return false;\n }\n\n if (error instanceof Error && 'status' in error) {\n const { status } = error as { status: number };\n // Don't retry 4xx except 429 (rate limit) and 408 (timeout)\n if (status >= 400 && status < 500 && status !== 429 && status !== 408) {\n return false;\n }\n }\n return true;\n}\n\n// ============================================================================\n// HTTP ERROR\n// ============================================================================\n\nexport class HttpError extends Error {\n readonly status: number;\n\n readonly statusText: string;\n\n readonly url: string;\n\n readonly body: unknown;\n\n constructor(\n message: string,\n status: number,\n statusText: string,\n url: string,\n body?: unknown,\n ) {\n super(message);\n this.name = 'HttpError';\n this.status = status;\n this.statusText = statusText;\n this.url = url;\n this.body = body;\n }\n}\n"]}
|
|
@@ -64,6 +64,13 @@ export type ApiPlatformClientOptions = {
|
|
|
64
64
|
clientVersion?: string;
|
|
65
65
|
/** Function to get bearer token for authenticated requests */
|
|
66
66
|
getBearerToken?: () => Promise<string | undefined>;
|
|
67
|
+
/**
|
|
68
|
+
* Max time (ms) to wait for `getBearerToken` before sending the request
|
|
69
|
+
* unauthenticated. The token keeps resolving in the background and is used by
|
|
70
|
+
* later requests. Set to `0` to always wait for the token.
|
|
71
|
+
* Defaults to {@link DEFAULT_AUTH_TOKEN_TIMEOUT}.
|
|
72
|
+
*/
|
|
73
|
+
authTokenTimeout?: number;
|
|
67
74
|
/** Optional custom QueryClient instance */
|
|
68
75
|
queryClient?: QueryClient;
|
|
69
76
|
};
|
|
@@ -110,7 +117,6 @@ export declare const API_URLS: {
|
|
|
110
117
|
};
|
|
111
118
|
/** Stale times for different data types (ms) */
|
|
112
119
|
export declare const STALE_TIMES: {
|
|
113
|
-
readonly AUTH_TOKEN: number;
|
|
114
120
|
readonly PRICES: number;
|
|
115
121
|
readonly BALANCES: number;
|
|
116
122
|
readonly NETWORKS: number;
|
|
@@ -122,6 +128,11 @@ export declare const STALE_TIMES: {
|
|
|
122
128
|
readonly TRANSACTIONS: number;
|
|
123
129
|
readonly DEFAULT: number;
|
|
124
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* Default max time (ms) to wait for the bearer token before falling back to an
|
|
133
|
+
* unauthenticated request.
|
|
134
|
+
*/
|
|
135
|
+
export declare const DEFAULT_AUTH_TOKEN_TIMEOUT = 500;
|
|
125
136
|
/** Garbage collection times (ms) */
|
|
126
137
|
export declare const GC_TIMES: {
|
|
127
138
|
readonly DEFAULT: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-types.d.cts","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"shared-types.d.cts","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -64,6 +64,13 @@ export type ApiPlatformClientOptions = {
|
|
|
64
64
|
clientVersion?: string;
|
|
65
65
|
/** Function to get bearer token for authenticated requests */
|
|
66
66
|
getBearerToken?: () => Promise<string | undefined>;
|
|
67
|
+
/**
|
|
68
|
+
* Max time (ms) to wait for `getBearerToken` before sending the request
|
|
69
|
+
* unauthenticated. The token keeps resolving in the background and is used by
|
|
70
|
+
* later requests. Set to `0` to always wait for the token.
|
|
71
|
+
* Defaults to {@link DEFAULT_AUTH_TOKEN_TIMEOUT}.
|
|
72
|
+
*/
|
|
73
|
+
authTokenTimeout?: number;
|
|
67
74
|
/** Optional custom QueryClient instance */
|
|
68
75
|
queryClient?: QueryClient;
|
|
69
76
|
};
|
|
@@ -110,7 +117,6 @@ export declare const API_URLS: {
|
|
|
110
117
|
};
|
|
111
118
|
/** Stale times for different data types (ms) */
|
|
112
119
|
export declare const STALE_TIMES: {
|
|
113
|
-
readonly AUTH_TOKEN: number;
|
|
114
120
|
readonly PRICES: number;
|
|
115
121
|
readonly BALANCES: number;
|
|
116
122
|
readonly NETWORKS: number;
|
|
@@ -122,6 +128,11 @@ export declare const STALE_TIMES: {
|
|
|
122
128
|
readonly TRANSACTIONS: number;
|
|
123
129
|
readonly DEFAULT: number;
|
|
124
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* Default max time (ms) to wait for the bearer token before falling back to an
|
|
133
|
+
* unauthenticated request.
|
|
134
|
+
*/
|
|
135
|
+
export declare const DEFAULT_AUTH_TOKEN_TIMEOUT = 500;
|
|
125
136
|
/** Garbage collection times (ms) */
|
|
126
137
|
export declare const GC_TIMES: {
|
|
127
138
|
readonly DEFAULT: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-types.d.mts","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"shared-types.d.mts","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,6BAA6B;AAM3E;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAEzB,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,MAAM,GACN,KAAK,GACL,KAAK,GAEL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,CAAC;AAEV;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iCAAiC;IACjC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iCAAiC;IACjC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kCAAkC;IAClC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kCAAkC;IAClC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,mCAAmC;IACnC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iCAAiC;IACjC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,wBAAwB,EAAE,MAAM,CAAC;IACjC,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yBAAyB;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAMF,MAAM,MAAM,wBAAwB,GAAG;IACrC,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACnD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,GAAG,OAAO,CACT,IAAI,CACF,iBAAiB,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,EAC1C,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAChD,CACF,GAAG;IACA,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEJ;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,CAAC,EAAE,YAAY,GACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAcrC;AAMD,oBAAoB;AACpB,eAAO,MAAM,QAAQ;;;;;CAKX,CAAC;AAEX,gDAAgD;AAChD,eAAO,MAAM,WAAW;;;;;;;;;;;CAWd,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,oCAAoC;AACpC,eAAO,MAAM,QAAQ;;;;CAIX,CAAC;AAEX,0BAA0B;AAC1B,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAMX;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAczE;AAMD,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;gBAGrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,OAAO;CASjB"}
|
|
@@ -29,7 +29,6 @@ export const API_URLS = {
|
|
|
29
29
|
};
|
|
30
30
|
/** Stale times for different data types (ms) */
|
|
31
31
|
export const STALE_TIMES = {
|
|
32
|
-
AUTH_TOKEN: 5 * 60 * 1000, // 5 minutes - cache the auth token
|
|
33
32
|
PRICES: 30 * 1000, // 30 seconds
|
|
34
33
|
BALANCES: 60 * 1000, // 1 minute
|
|
35
34
|
NETWORKS: 10 * 60 * 1000, // 10 minutes
|
|
@@ -41,6 +40,11 @@ export const STALE_TIMES = {
|
|
|
41
40
|
TRANSACTIONS: 30 * 1000, // 30 seconds
|
|
42
41
|
DEFAULT: 30 * 1000, // 30 seconds
|
|
43
42
|
};
|
|
43
|
+
/**
|
|
44
|
+
* Default max time (ms) to wait for the bearer token before falling back to an
|
|
45
|
+
* unauthenticated request.
|
|
46
|
+
*/
|
|
47
|
+
export const DEFAULT_AUTH_TOKEN_TIMEOUT = 500;
|
|
44
48
|
/** Garbage collection times (ms) */
|
|
45
49
|
export const GC_TIMES = {
|
|
46
50
|
DEFAULT: 5 * 60 * 1000, // 5 minutes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-types.mjs","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared types, constants, and utilities for the API Platform Client.\n */\n\nimport type { FetchQueryOptions, QueryClient } from '@tanstack/query-core';\n\n// ============================================================================\n// SHARED TYPES\n// ============================================================================\n\n/**\n * Pagination info for paginated responses\n */\nexport type PageInfo = {\n count: number;\n hasNextPage: boolean;\n cursor?: string;\n};\n\n/**\n * Supported currencies for Price API\n */\nexport type SupportedCurrency =\n // Crypto\n | 'btc'\n | 'eth'\n | 'ltc'\n | 'bch'\n | 'bnb'\n | 'eos'\n | 'xrp'\n | 'xlm'\n | 'link'\n | 'dot'\n | 'yfi'\n // Fiat\n | 'usd'\n | 'aed'\n | 'ars'\n | 'aud'\n | 'bdt'\n | 'bhd'\n | 'bmd'\n | 'brl'\n | 'cad'\n | 'chf'\n | 'clp'\n | 'cny'\n | 'czk'\n | 'dkk'\n | 'eur'\n | 'gbp'\n | 'gel'\n | 'hkd'\n | 'huf'\n | 'idr'\n | 'ils'\n | 'inr'\n | 'jpy'\n | 'krw'\n | 'kwd'\n | 'lkr'\n | 'mmk'\n | 'mxn'\n | 'myr'\n | 'ngn'\n | 'nok'\n | 'nzd'\n | 'php'\n | 'pkr'\n | 'pln'\n | 'rub'\n | 'sar'\n | 'sek'\n | 'sgd'\n | 'thb'\n | 'try'\n | 'twd'\n | 'uah'\n | 'vef'\n | 'vnd'\n | 'zar';\n\n/**\n * Market data details from Price API spot-prices endpoint\n */\nexport type MarketDataDetails = {\n /** Current price in the requested currency */\n price: number;\n /** Currency code (e.g., 'ETH', 'USD') */\n currency: string;\n /** 24h price change amount */\n priceChange1d: number;\n /** 24h price change percentage */\n pricePercentChange1d: number;\n /** 1h price change percentage */\n pricePercentChange1h: number;\n /** 7d price change percentage */\n pricePercentChange7d: number;\n /** 14d price change percentage */\n pricePercentChange14d: number;\n /** 30d price change percentage */\n pricePercentChange30d: number;\n /** 200d price change percentage */\n pricePercentChange200d: number;\n /** 1y price change percentage */\n pricePercentChange1y: number;\n /** Market capitalization */\n marketCap: number;\n /** Market cap 24h change percentage */\n marketCapPercentChange1d: number;\n /** All-time high price */\n allTimeHigh: number;\n /** All-time low price */\n allTimeLow: number;\n /** 24h high price */\n high1d: number;\n /** 24h low price */\n low1d: number;\n /** Total trading volume */\n totalVolume: number;\n /** Circulating supply */\n circulatingSupply: number;\n /** Diluted market cap */\n dilutedMarketCap: number;\n};\n\n// ============================================================================\n// CLIENT OPTIONS\n// ============================================================================\n\nexport type ApiPlatformClientOptions = {\n /** Client product identifier (e.g., 'metamask-extension') */\n clientProduct: string;\n /** Optional client version */\n clientVersion?: string;\n /** Function to get bearer token for authenticated requests */\n getBearerToken?: () => Promise<string | undefined>;\n /** Optional custom QueryClient instance */\n queryClient?: QueryClient;\n};\n\n/**\n * Options for API fetch and query methods.\n * Extends TanStack Query options (e.g. select, initialPageParam, retry) so callers\n * can pass them through to useQuery / useInfiniteQuery. queryKey and queryFn are\n * always set by the client and cannot be overridden.\n * staleTime and gcTime are explicitly number (not function) so that client defaults apply without type conflicts.\n */\nexport type FetchOptions = {\n /** Custom stale time (ms). */\n staleTime?: number;\n /** Custom GC time (ms). */\n gcTime?: number;\n /**\n * When true, bypass caching for this request: the client-side query cache is\n * skipped (stale time defaults to 0) and, on endpoints that support it, a\n * random `bypassServerCache` query param is appended so server-side HTTP caches\n * (keyed on the full URL) miss. Use sparingly — only when a hard refresh is\n * required, e.g. right after a transaction confirms.\n */\n bypassServerCache?: boolean;\n} & Partial<\n Omit<\n FetchQueryOptions<unknown, Error, unknown>,\n 'queryKey' | 'queryFn' | 'staleTime' | 'gcTime'\n >\n> & {\n /** Allowed for infinite query options (e.g. useInfiniteQuery). */\n initialPageParam?: unknown;\n };\n\n/**\n * Returns options with queryKey and queryFn omitted, for merging into\n * get*QueryOptions return values without overwriting the client's queryKey/queryFn.\n * Return type is intentionally loose so that spreading into FetchQueryOptions<T>\n * does not conflict with T-specific option types (e.g. select, staleTime).\n *\n * @param options - Optional FetchOptions from the caller.\n * @returns Options safe to spread into query options, or undefined.\n */\nexport function getQueryOptionsOverrides(\n options?: FetchOptions,\n): Record<string, unknown> | undefined {\n if (options === null || options === undefined) {\n return undefined;\n }\n const {\n queryKey: _qk,\n queryFn: _qf,\n bypassServerCache: _bc,\n ...rest\n } = options as FetchOptions & {\n queryKey?: unknown;\n queryFn?: unknown;\n };\n return rest as Record<string, unknown>;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\n/** API Base URLs */\nexport const API_URLS = {\n ACCOUNTS: 'https://accounts.api.cx.metamask.io',\n PRICES: 'https://price.api.cx.metamask.io',\n TOKEN: 'https://token.api.cx.metamask.io',\n TOKENS: 'https://tokens.api.cx.metamask.io',\n} as const;\n\n/** Stale times for different data types (ms) */\nexport const STALE_TIMES = {\n AUTH_TOKEN: 5 * 60 * 1000, // 5 minutes - cache the auth token\n PRICES: 30 * 1000, // 30 seconds\n BALANCES: 60 * 1000, // 1 minute\n NETWORKS: 10 * 60 * 1000, // 10 minutes\n SUPPORTED_NETWORKS: 30 * 60 * 1000, // 30 minutes\n TOKEN_METADATA: 5 * 60 * 1000, // 5 minutes\n TOKEN_LIST: 10 * 60 * 1000, // 10 minutes\n EXCHANGE_RATES: 5 * 60 * 1000, // 5 minutes\n TRENDING: 2 * 60 * 1000, // 2 minutes\n TRANSACTIONS: 30 * 1000, // 30 seconds\n DEFAULT: 30 * 1000, // 30 seconds\n} as const;\n\n/** Garbage collection times (ms) */\nexport const GC_TIMES = {\n DEFAULT: 5 * 60 * 1000, // 5 minutes\n EXTENDED: 30 * 60 * 1000, // 30 minutes\n SHORT: 2 * 60 * 1000, // 2 minutes\n} as const;\n\n/** Retry configuration */\nexport const RETRY_CONFIG = {\n MAX_RETRIES: 3,\n BASE_DELAY: 1000,\n MAX_DELAY: 5_000,\n} as const;\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Calculate retry delay with exponential backoff and jitter.\n *\n * @param attemptIndex - The current retry attempt (0-indexed).\n * @returns The delay in milliseconds before the next retry.\n */\nexport function calculateRetryDelay(attemptIndex: number): number {\n const delay = Math.min(\n RETRY_CONFIG.BASE_DELAY * 2 ** attemptIndex,\n RETRY_CONFIG.MAX_DELAY,\n );\n return delay / 2 + Math.random() * (delay / 2);\n}\n\n/**\n * Determine if a failed request should be retried.\n *\n * @param failureCount - The number of failures so far (1 = first failure).\n * @param error - The error from the failed request.\n * @returns True if the request should be retried, false otherwise.\n */\nexport function shouldRetry(failureCount: number, error: unknown): boolean {\n // Allow up to MAX_RETRIES retries (e.g., MAX_RETRIES=3 means 4 total attempts)\n if (failureCount > RETRY_CONFIG.MAX_RETRIES) {\n return false;\n }\n\n if (error instanceof Error && 'status' in error) {\n const { status } = error as { status: number };\n // Don't retry 4xx except 429 (rate limit) and 408 (timeout)\n if (status >= 400 && status < 500 && status !== 429 && status !== 408) {\n return false;\n }\n }\n return true;\n}\n\n// ============================================================================\n// HTTP ERROR\n// ============================================================================\n\nexport class HttpError extends Error {\n readonly status: number;\n\n readonly statusText: string;\n\n readonly url: string;\n\n readonly body: unknown;\n\n constructor(\n message: string,\n status: number,\n statusText: string,\n url: string,\n body?: unknown,\n ) {\n super(message);\n this.name = 'HttpError';\n this.status = status;\n this.statusText = statusText;\n this.url = url;\n this.body = body;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shared-types.mjs","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared types, constants, and utilities for the API Platform Client.\n */\n\nimport type { FetchQueryOptions, QueryClient } from '@tanstack/query-core';\n\n// ============================================================================\n// SHARED TYPES\n// ============================================================================\n\n/**\n * Pagination info for paginated responses\n */\nexport type PageInfo = {\n count: number;\n hasNextPage: boolean;\n cursor?: string;\n};\n\n/**\n * Supported currencies for Price API\n */\nexport type SupportedCurrency =\n // Crypto\n | 'btc'\n | 'eth'\n | 'ltc'\n | 'bch'\n | 'bnb'\n | 'eos'\n | 'xrp'\n | 'xlm'\n | 'link'\n | 'dot'\n | 'yfi'\n // Fiat\n | 'usd'\n | 'aed'\n | 'ars'\n | 'aud'\n | 'bdt'\n | 'bhd'\n | 'bmd'\n | 'brl'\n | 'cad'\n | 'chf'\n | 'clp'\n | 'cny'\n | 'czk'\n | 'dkk'\n | 'eur'\n | 'gbp'\n | 'gel'\n | 'hkd'\n | 'huf'\n | 'idr'\n | 'ils'\n | 'inr'\n | 'jpy'\n | 'krw'\n | 'kwd'\n | 'lkr'\n | 'mmk'\n | 'mxn'\n | 'myr'\n | 'ngn'\n | 'nok'\n | 'nzd'\n | 'php'\n | 'pkr'\n | 'pln'\n | 'rub'\n | 'sar'\n | 'sek'\n | 'sgd'\n | 'thb'\n | 'try'\n | 'twd'\n | 'uah'\n | 'vef'\n | 'vnd'\n | 'zar';\n\n/**\n * Market data details from Price API spot-prices endpoint\n */\nexport type MarketDataDetails = {\n /** Current price in the requested currency */\n price: number;\n /** Currency code (e.g., 'ETH', 'USD') */\n currency: string;\n /** 24h price change amount */\n priceChange1d: number;\n /** 24h price change percentage */\n pricePercentChange1d: number;\n /** 1h price change percentage */\n pricePercentChange1h: number;\n /** 7d price change percentage */\n pricePercentChange7d: number;\n /** 14d price change percentage */\n pricePercentChange14d: number;\n /** 30d price change percentage */\n pricePercentChange30d: number;\n /** 200d price change percentage */\n pricePercentChange200d: number;\n /** 1y price change percentage */\n pricePercentChange1y: number;\n /** Market capitalization */\n marketCap: number;\n /** Market cap 24h change percentage */\n marketCapPercentChange1d: number;\n /** All-time high price */\n allTimeHigh: number;\n /** All-time low price */\n allTimeLow: number;\n /** 24h high price */\n high1d: number;\n /** 24h low price */\n low1d: number;\n /** Total trading volume */\n totalVolume: number;\n /** Circulating supply */\n circulatingSupply: number;\n /** Diluted market cap */\n dilutedMarketCap: number;\n};\n\n// ============================================================================\n// CLIENT OPTIONS\n// ============================================================================\n\nexport type ApiPlatformClientOptions = {\n /** Client product identifier (e.g., 'metamask-extension') */\n clientProduct: string;\n /** Optional client version */\n clientVersion?: string;\n /** Function to get bearer token for authenticated requests */\n getBearerToken?: () => Promise<string | undefined>;\n /**\n * Max time (ms) to wait for `getBearerToken` before sending the request\n * unauthenticated. The token keeps resolving in the background and is used by\n * later requests. Set to `0` to always wait for the token.\n * Defaults to {@link DEFAULT_AUTH_TOKEN_TIMEOUT}.\n */\n authTokenTimeout?: number;\n /** Optional custom QueryClient instance */\n queryClient?: QueryClient;\n};\n\n/**\n * Options for API fetch and query methods.\n * Extends TanStack Query options (e.g. select, initialPageParam, retry) so callers\n * can pass them through to useQuery / useInfiniteQuery. queryKey and queryFn are\n * always set by the client and cannot be overridden.\n * staleTime and gcTime are explicitly number (not function) so that client defaults apply without type conflicts.\n */\nexport type FetchOptions = {\n /** Custom stale time (ms). */\n staleTime?: number;\n /** Custom GC time (ms). */\n gcTime?: number;\n /**\n * When true, bypass caching for this request: the client-side query cache is\n * skipped (stale time defaults to 0) and, on endpoints that support it, a\n * random `bypassServerCache` query param is appended so server-side HTTP caches\n * (keyed on the full URL) miss. Use sparingly — only when a hard refresh is\n * required, e.g. right after a transaction confirms.\n */\n bypassServerCache?: boolean;\n} & Partial<\n Omit<\n FetchQueryOptions<unknown, Error, unknown>,\n 'queryKey' | 'queryFn' | 'staleTime' | 'gcTime'\n >\n> & {\n /** Allowed for infinite query options (e.g. useInfiniteQuery). */\n initialPageParam?: unknown;\n };\n\n/**\n * Returns options with queryKey and queryFn omitted, for merging into\n * get*QueryOptions return values without overwriting the client's queryKey/queryFn.\n * Return type is intentionally loose so that spreading into FetchQueryOptions<T>\n * does not conflict with T-specific option types (e.g. select, staleTime).\n *\n * @param options - Optional FetchOptions from the caller.\n * @returns Options safe to spread into query options, or undefined.\n */\nexport function getQueryOptionsOverrides(\n options?: FetchOptions,\n): Record<string, unknown> | undefined {\n if (options === null || options === undefined) {\n return undefined;\n }\n const {\n queryKey: _qk,\n queryFn: _qf,\n bypassServerCache: _bc,\n ...rest\n } = options as FetchOptions & {\n queryKey?: unknown;\n queryFn?: unknown;\n };\n return rest as Record<string, unknown>;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\n/** API Base URLs */\nexport const API_URLS = {\n ACCOUNTS: 'https://accounts.api.cx.metamask.io',\n PRICES: 'https://price.api.cx.metamask.io',\n TOKEN: 'https://token.api.cx.metamask.io',\n TOKENS: 'https://tokens.api.cx.metamask.io',\n} as const;\n\n/** Stale times for different data types (ms) */\nexport const STALE_TIMES = {\n PRICES: 30 * 1000, // 30 seconds\n BALANCES: 60 * 1000, // 1 minute\n NETWORKS: 10 * 60 * 1000, // 10 minutes\n SUPPORTED_NETWORKS: 30 * 60 * 1000, // 30 minutes\n TOKEN_METADATA: 5 * 60 * 1000, // 5 minutes\n TOKEN_LIST: 10 * 60 * 1000, // 10 minutes\n EXCHANGE_RATES: 5 * 60 * 1000, // 5 minutes\n TRENDING: 2 * 60 * 1000, // 2 minutes\n TRANSACTIONS: 30 * 1000, // 30 seconds\n DEFAULT: 30 * 1000, // 30 seconds\n} as const;\n\n/**\n * Default max time (ms) to wait for the bearer token before falling back to an\n * unauthenticated request.\n */\nexport const DEFAULT_AUTH_TOKEN_TIMEOUT = 500;\n\n/** Garbage collection times (ms) */\nexport const GC_TIMES = {\n DEFAULT: 5 * 60 * 1000, // 5 minutes\n EXTENDED: 30 * 60 * 1000, // 30 minutes\n SHORT: 2 * 60 * 1000, // 2 minutes\n} as const;\n\n/** Retry configuration */\nexport const RETRY_CONFIG = {\n MAX_RETRIES: 3,\n BASE_DELAY: 1000,\n MAX_DELAY: 5_000,\n} as const;\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Calculate retry delay with exponential backoff and jitter.\n *\n * @param attemptIndex - The current retry attempt (0-indexed).\n * @returns The delay in milliseconds before the next retry.\n */\nexport function calculateRetryDelay(attemptIndex: number): number {\n const delay = Math.min(\n RETRY_CONFIG.BASE_DELAY * 2 ** attemptIndex,\n RETRY_CONFIG.MAX_DELAY,\n );\n return delay / 2 + Math.random() * (delay / 2);\n}\n\n/**\n * Determine if a failed request should be retried.\n *\n * @param failureCount - The number of failures so far (1 = first failure).\n * @param error - The error from the failed request.\n * @returns True if the request should be retried, false otherwise.\n */\nexport function shouldRetry(failureCount: number, error: unknown): boolean {\n // Allow up to MAX_RETRIES retries (e.g., MAX_RETRIES=3 means 4 total attempts)\n if (failureCount > RETRY_CONFIG.MAX_RETRIES) {\n return false;\n }\n\n if (error instanceof Error && 'status' in error) {\n const { status } = error as { status: number };\n // Don't retry 4xx except 429 (rate limit) and 408 (timeout)\n if (status >= 400 && status < 500 && status !== 429 && status !== 408) {\n return false;\n }\n }\n return true;\n}\n\n// ============================================================================\n// HTTP ERROR\n// ============================================================================\n\nexport class HttpError extends Error {\n readonly status: number;\n\n readonly statusText: string;\n\n readonly url: string;\n\n readonly body: unknown;\n\n constructor(\n message: string,\n status: number,\n statusText: string,\n url: string,\n body?: unknown,\n ) {\n super(message);\n this.name = 'HttpError';\n this.status = status;\n this.statusText = statusText;\n this.url = url;\n this.body = body;\n }\n}\n"]}
|