@metamask-previews/core-backend 5.0.0-preview-3ec2a74 → 5.0.0-preview-6ae8a59c

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 CHANGED
@@ -19,10 +19,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
19
19
  ### Changed
20
20
 
21
21
  - Upgrade `@metamask/utils` from `^11.8.1` to `^11.9.0` ([#7511](https://github.com/MetaMask/core/pull/7511))
22
- - Move peer dependencies for controller and service packages to direct dependencies ([#7209](https://github.com/MetaMask/core/pull/7209), [#7604](https://github.com/MetaMask/core/pull/7604), [#7642](https://github.com/MetaMask/core/pull/7642))
22
+ - Move peer dependencies for controller and service packages to direct dependencies ([#7209](https://github.com/MetaMask/core/pull/7209), [#7604](https://github.com/MetaMask/core/pull/7604), [#7642](https://github.com/MetaMask/core/pull/7642), [#7713](https://github.com/MetaMask/core/pull/7713))
23
23
  - The dependencies moved are:
24
24
  - `@metamask/accounts-controller` (^35.0.2)
25
- - `@metamask/keyring-controller` (^25.0.0)
25
+ - `@metamask/keyring-controller` (^25.1.0)
26
26
  - In clients, it is now possible for multiple versions of these packages to exist in the dependency tree.
27
27
  - For example, this scenario would be valid: a client relies on `@metamask/controller-a` 1.0.0 and `@metamask/controller-b` 1.0.0, and `@metamask/controller-b` depends on `@metamask/controller-a` 1.1.0.
28
28
  - Note, however, that the versions specified in the client's `package.json` always "win", and you are expected to keep them up to date so as not to break controller and service intercommunication.
@@ -51,6 +51,7 @@ exports.createApiPlatformClient = exports.ApiPlatformClient = void 0;
51
51
  const query_core_1 = require("@tanstack/query-core");
52
52
  // Import API clients from subfolders
53
53
  const accounts_1 = require("./accounts/index.cjs");
54
+ const base_client_1 = require("./base-client.cjs");
54
55
  const prices_1 = require("./prices/index.cjs");
55
56
  const shared_types_1 = require("./shared-types.cjs");
56
57
  const token_1 = require("./token/index.cjs");
@@ -151,10 +152,13 @@ class ApiPlatformClient {
151
152
  /**
152
153
  * Invalidate the cached auth token.
153
154
  * Call this when the user logs out or the token expires.
155
+ *
156
+ * Uses resetQueries() instead of invalidateQueries() to completely remove
157
+ * the cached value, ensuring the next request fetches a fresh token immediately.
154
158
  */
155
159
  async invalidateAuthToken() {
156
- await __classPrivateFieldGet(this, _ApiPlatformClient_sharedQueryClient, "f").invalidateQueries({
157
- queryKey: shared_types_1.authQueryKeys.bearerToken(),
160
+ await __classPrivateFieldGet(this, _ApiPlatformClient_sharedQueryClient, "f").resetQueries({
161
+ queryKey: base_client_1.authQueryKeys.bearerToken(),
158
162
  });
159
163
  }
160
164
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ApiPlatformClient.cjs","sourceRoot":"","sources":["../../src/api/ApiPlatformClient.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;;;;;;;;;;;;;;;AAEH,qDAAmD;AAGnD,qCAAqC;AACrC,mDAA+C;AAC/C,+CAA2C;AAC3C,qDAMwB;AAExB,6CAAyC;AACzC,+CAA2C;AAE3C,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E;;;;;;;;;GASG;AACH,MAAa,iBAAiB;IA8B5B,YAAY,OAAiC;QAL7C;;WAEG;QACM,uDAAgC;QAGvC,iEAAiE;QACjE,uBAAA,IAAI,wCACF,OAAO,CAAC,WAAW;YACnB,IAAI,wBAAW,CAAC;gBACd,cAAc,EAAE;oBACd,OAAO,EAAE;wBACP,SAAS,EAAE,0BAAW,CAAC,OAAO;wBAC9B,MAAM,EAAE,uBAAQ,CAAC,OAAO;wBACxB,KAAK,EAAE,0BAAW;wBAClB,UAAU,EAAE,kCAAmB;wBAC/B,oBAAoB,EAAE,KAAK;wBAC3B,WAAW,EAAE,QAAQ;qBACtB;iBACF;aACF,CAAC,MAAA,CAAC;QAEL,iDAAiD;QACjD,MAAM,aAAa,GAA6B;YAC9C,GAAG,OAAO;YACV,WAAW,EAAE,uBAAA,IAAI,4CAAmB;SACrC,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,IAAI,4BAAiB,CAAC,aAAa,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,GAAG,IAAI,wBAAe,CAAC,aAAa,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,GAAG,IAAI,sBAAc,CAAC,aAAa,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,GAAG,IAAI,wBAAe,CAAC,aAAa,CAAC,CAAC;IACnD,CAAC;IAED,6EAA6E;IAC7E,oDAAoD;IACpD,6EAA6E;IAE7E;;;;OAIG;IACH,IAAI,WAAW;QACb,OAAO,uBAAA,IAAI,4CAAmB,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAa,QAAkB;QAC1C,OAAO,uBAAA,IAAI,4CAAmB,CAAC,YAAY,CAAa,QAAQ,CAAC,CAAC;IACpE,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAa,QAAkB,EAAE,IAAgB;QAC5D,uBAAA,IAAI,4CAAmB,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,QAAkB;QAC3B,OAAO,uBAAA,IAAI,4CAAmB,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACH,KAAK;QACH,uBAAA,IAAI,4CAAmB,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa;QACjB,MAAM,uBAAA,IAAI,4CAAmB,CAAC,iBAAiB,EAAE,CAAC;IACpD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,mBAAmB;QACvB,MAAM,uBAAA,IAAI,4CAAmB,CAAC,iBAAiB,CAAC;YAC9C,QAAQ,EAAE,4BAAa,CAAC,WAAW,EAAE;SACtC,CAAC,CAAC;IACL,CAAC;CACF;AA7HD,8CA6HC;;AAED;;;;;GAKG;AACH,SAAgB,uBAAuB,CACrC,OAAiC;IAEjC,OAAO,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC;AAJD,0DAIC","sourcesContent":["/**\n * ApiPlatformClient - MetaMask API Platform Client\n *\n * A comprehensive API client that uses @tanstack/query-core directly for:\n * - Automatic request deduplication\n * - Intelligent caching\n * - Automatic retries with exponential backoff\n *\n * Provides unified access to all MetaMask backend APIs:\n * - Accounts API (accounts.api.cx.metamask.io)\n * - Price API (price.api.cx.metamask.io)\n * - Token API (token.api.cx.metamask.io)\n * - Tokens API (tokens.api.cx.metamask.io)\n *\n * @example\n * ```typescript\n * const client = new ApiPlatformClient({\n * clientProduct: 'metamask-extension',\n * getBearerToken: async () => token,\n * });\n *\n * // Access API methods through sub-clients\n * const networks = await client.accounts.fetchV2SupportedNetworks();\n * const balances = await client.accounts.fetchV5MultiAccountBalances(accountIds);\n * const prices = await client.prices.fetchV3SpotPrices(assetIds);\n * const tokenList = await client.token.fetchTokenList(1);\n * const assets = await client.tokens.fetchV3Assets(assetIds);\n *\n * // Cache management\n * await client.invalidateAll(); // Invalidate all caches\n * await client.invalidateAuthToken(); // Invalidate auth token\n * await client.accounts.invalidateBalances(); // Domain-specific via sub-client\n * await client.prices.invalidatePrices(); // Domain-specific via sub-client\n * ```\n */\n\nimport { QueryClient } from '@tanstack/query-core';\nimport type { QueryKey } from '@tanstack/query-core';\n\n// Import API clients from subfolders\nimport { AccountsApiClient } from './accounts';\nimport { PricesApiClient } from './prices';\nimport {\n STALE_TIMES,\n GC_TIMES,\n authQueryKeys,\n shouldRetry,\n calculateRetryDelay,\n} from './shared-types';\nimport type { ApiPlatformClientOptions } from './shared-types';\nimport { TokenApiClient } from './token';\nimport { TokensApiClient } from './tokens';\n\n// ============================================================================\n// UNIFIED API CLIENT\n// ============================================================================\n\n/**\n * MetaMask API Platform Client with TanStack Query caching.\n * Provides cached access to all MetaMask backend APIs through a unified interface.\n *\n * Access API methods through the sub-clients:\n * - `client.accounts` - Accounts API (balances, transactions, NFTs, etc.)\n * - `client.prices` - Prices API (spot prices, exchange rates, historical prices)\n * - `client.token` - Token API (token metadata, trending, top gainers)\n * - `client.tokens` - Tokens API (bulk asset operations, supported networks)\n */\nexport class ApiPlatformClient {\n /**\n * Accounts API client.\n * Provides methods for balances, transactions, relationships, NFTs, and token discovery.\n */\n readonly accounts: AccountsApiClient;\n\n /**\n * Prices API client.\n * Provides methods for spot prices, exchange rates, and historical prices.\n */\n readonly prices: PricesApiClient;\n\n /**\n * Token API client.\n * Provides methods for token metadata, networks, trending tokens, and top assets.\n */\n readonly token: TokenApiClient;\n\n /**\n * Tokens API client.\n * Provides methods for bulk asset operations and supported networks.\n */\n readonly tokens: TokensApiClient;\n\n /**\n * Shared QueryClient instance used by all sub-clients.\n */\n readonly #sharedQueryClient: QueryClient;\n\n constructor(options: ApiPlatformClientOptions) {\n // Create or use provided QueryClient - shared by all sub-clients\n this.#sharedQueryClient =\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 // Pass the shared QueryClient to all sub-clients\n const sharedOptions: ApiPlatformClientOptions = {\n ...options,\n queryClient: this.#sharedQueryClient,\n };\n\n this.accounts = new AccountsApiClient(sharedOptions);\n this.prices = new PricesApiClient(sharedOptions);\n this.token = new TokenApiClient(sharedOptions);\n this.tokens = new TokensApiClient(sharedOptions);\n }\n\n // ==========================================================================\n // CACHE MANAGEMENT (operates on shared QueryClient)\n // ==========================================================================\n\n /**\n * Get the underlying QueryClient (for advanced usage).\n *\n * @returns The underlying QueryClient instance.\n */\n get queryClient(): QueryClient {\n return this.#sharedQueryClient;\n }\n\n /**\n * Get cached data for a query key.\n *\n * @param queryKey - The query key to look up.\n * @returns The cached data or undefined.\n */\n getCachedData<CachedData>(queryKey: QueryKey): CachedData | undefined {\n return this.#sharedQueryClient.getQueryData<CachedData>(queryKey);\n }\n\n /**\n * Set cached data for a query key.\n *\n * @param queryKey - The query key to set data for.\n * @param data - The data to cache.\n */\n setCachedData<CachedData>(queryKey: QueryKey, data: CachedData): void {\n this.#sharedQueryClient.setQueryData(queryKey, data);\n }\n\n /**\n * Check if a query is currently fetching.\n *\n * @param queryKey - The query key to check.\n * @returns True if the query is currently fetching.\n */\n isFetching(queryKey: QueryKey): boolean {\n return this.#sharedQueryClient.isFetching({ queryKey }) > 0;\n }\n\n /**\n * Clear all cached data across all sub-clients.\n */\n clear(): void {\n this.#sharedQueryClient.clear();\n }\n\n /**\n * Invalidate all queries across all sub-clients.\n */\n async invalidateAll(): Promise<void> {\n await this.#sharedQueryClient.invalidateQueries();\n }\n\n /**\n * Invalidate the cached auth token.\n * Call this when the user logs out or the token expires.\n */\n async invalidateAuthToken(): Promise<void> {\n await this.#sharedQueryClient.invalidateQueries({\n queryKey: authQueryKeys.bearerToken(),\n });\n }\n}\n\n/**\n * Factory function to create an ApiPlatformClient.\n *\n * @param options - Configuration options for the client.\n * @returns A new ApiPlatformClient instance.\n */\nexport function createApiPlatformClient(\n options: ApiPlatformClientOptions,\n): ApiPlatformClient {\n return new ApiPlatformClient(options);\n}\n"]}
1
+ {"version":3,"file":"ApiPlatformClient.cjs","sourceRoot":"","sources":["../../src/api/ApiPlatformClient.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;;;;;;;;;;;;;;;AAEH,qDAAmD;AAGnD,qCAAqC;AACrC,mDAA+C;AAC/C,mDAA8C;AAC9C,+CAA2C;AAC3C,qDAKwB;AAExB,6CAAyC;AACzC,+CAA2C;AAE3C,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E;;;;;;;;;GASG;AACH,MAAa,iBAAiB;IA8B5B,YAAY,OAAiC;QAL7C;;WAEG;QACM,uDAAgC;QAGvC,iEAAiE;QACjE,uBAAA,IAAI,wCACF,OAAO,CAAC,WAAW;YACnB,IAAI,wBAAW,CAAC;gBACd,cAAc,EAAE;oBACd,OAAO,EAAE;wBACP,SAAS,EAAE,0BAAW,CAAC,OAAO;wBAC9B,MAAM,EAAE,uBAAQ,CAAC,OAAO;wBACxB,KAAK,EAAE,0BAAW;wBAClB,UAAU,EAAE,kCAAmB;wBAC/B,oBAAoB,EAAE,KAAK;wBAC3B,WAAW,EAAE,QAAQ;qBACtB;iBACF;aACF,CAAC,MAAA,CAAC;QAEL,iDAAiD;QACjD,MAAM,aAAa,GAA6B;YAC9C,GAAG,OAAO;YACV,WAAW,EAAE,uBAAA,IAAI,4CAAmB;SACrC,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,IAAI,4BAAiB,CAAC,aAAa,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,GAAG,IAAI,wBAAe,CAAC,aAAa,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,GAAG,IAAI,sBAAc,CAAC,aAAa,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,GAAG,IAAI,wBAAe,CAAC,aAAa,CAAC,CAAC;IACnD,CAAC;IAED,6EAA6E;IAC7E,oDAAoD;IACpD,6EAA6E;IAE7E;;;;OAIG;IACH,IAAI,WAAW;QACb,OAAO,uBAAA,IAAI,4CAAmB,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAa,QAAkB;QAC1C,OAAO,uBAAA,IAAI,4CAAmB,CAAC,YAAY,CAAa,QAAQ,CAAC,CAAC;IACpE,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAa,QAAkB,EAAE,IAAgB;QAC5D,uBAAA,IAAI,4CAAmB,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,QAAkB;QAC3B,OAAO,uBAAA,IAAI,4CAAmB,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACH,KAAK;QACH,uBAAA,IAAI,4CAAmB,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa;QACjB,MAAM,uBAAA,IAAI,4CAAmB,CAAC,iBAAiB,EAAE,CAAC;IACpD,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,mBAAmB;QACvB,MAAM,uBAAA,IAAI,4CAAmB,CAAC,YAAY,CAAC;YACzC,QAAQ,EAAE,2BAAa,CAAC,WAAW,EAAE;SACtC,CAAC,CAAC;IACL,CAAC;CACF;AAhID,8CAgIC;;AAED;;;;;GAKG;AACH,SAAgB,uBAAuB,CACrC,OAAiC;IAEjC,OAAO,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC;AAJD,0DAIC","sourcesContent":["/**\n * ApiPlatformClient - MetaMask API Platform Client\n *\n * A comprehensive API client that uses @tanstack/query-core directly for:\n * - Automatic request deduplication\n * - Intelligent caching\n * - Automatic retries with exponential backoff\n *\n * Provides unified access to all MetaMask backend APIs:\n * - Accounts API (accounts.api.cx.metamask.io)\n * - Price API (price.api.cx.metamask.io)\n * - Token API (token.api.cx.metamask.io)\n * - Tokens API (tokens.api.cx.metamask.io)\n *\n * @example\n * ```typescript\n * const client = new ApiPlatformClient({\n * clientProduct: 'metamask-extension',\n * getBearerToken: async () => token,\n * });\n *\n * // Access API methods through sub-clients\n * const networks = await client.accounts.fetchV2SupportedNetworks();\n * const balances = await client.accounts.fetchV5MultiAccountBalances(accountIds);\n * const prices = await client.prices.fetchV3SpotPrices(assetIds);\n * const tokenList = await client.token.fetchTokenList(1);\n * const assets = await client.tokens.fetchV3Assets(assetIds);\n *\n * // Cache management\n * await client.invalidateAll(); // Invalidate all caches\n * await client.invalidateAuthToken(); // Invalidate auth token\n * await client.accounts.invalidateBalances(); // Domain-specific via sub-client\n * await client.prices.invalidatePrices(); // Domain-specific via sub-client\n * ```\n */\n\nimport { QueryClient } from '@tanstack/query-core';\nimport type { QueryKey } from '@tanstack/query-core';\n\n// Import API clients from subfolders\nimport { AccountsApiClient } from './accounts';\nimport { authQueryKeys } from './base-client';\nimport { PricesApiClient } from './prices';\nimport {\n STALE_TIMES,\n GC_TIMES,\n shouldRetry,\n calculateRetryDelay,\n} from './shared-types';\nimport type { ApiPlatformClientOptions } from './shared-types';\nimport { TokenApiClient } from './token';\nimport { TokensApiClient } from './tokens';\n\n// ============================================================================\n// UNIFIED API CLIENT\n// ============================================================================\n\n/**\n * MetaMask API Platform Client with TanStack Query caching.\n * Provides cached access to all MetaMask backend APIs through a unified interface.\n *\n * Access API methods through the sub-clients:\n * - `client.accounts` - Accounts API (balances, transactions, NFTs, etc.)\n * - `client.prices` - Prices API (spot prices, exchange rates, historical prices)\n * - `client.token` - Token API (token metadata, trending, top gainers)\n * - `client.tokens` - Tokens API (bulk asset operations, supported networks)\n */\nexport class ApiPlatformClient {\n /**\n * Accounts API client.\n * Provides methods for balances, transactions, relationships, NFTs, and token discovery.\n */\n readonly accounts: AccountsApiClient;\n\n /**\n * Prices API client.\n * Provides methods for spot prices, exchange rates, and historical prices.\n */\n readonly prices: PricesApiClient;\n\n /**\n * Token API client.\n * Provides methods for token metadata, networks, trending tokens, and top assets.\n */\n readonly token: TokenApiClient;\n\n /**\n * Tokens API client.\n * Provides methods for bulk asset operations and supported networks.\n */\n readonly tokens: TokensApiClient;\n\n /**\n * Shared QueryClient instance used by all sub-clients.\n */\n readonly #sharedQueryClient: QueryClient;\n\n constructor(options: ApiPlatformClientOptions) {\n // Create or use provided QueryClient - shared by all sub-clients\n this.#sharedQueryClient =\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 // Pass the shared QueryClient to all sub-clients\n const sharedOptions: ApiPlatformClientOptions = {\n ...options,\n queryClient: this.#sharedQueryClient,\n };\n\n this.accounts = new AccountsApiClient(sharedOptions);\n this.prices = new PricesApiClient(sharedOptions);\n this.token = new TokenApiClient(sharedOptions);\n this.tokens = new TokensApiClient(sharedOptions);\n }\n\n // ==========================================================================\n // CACHE MANAGEMENT (operates on shared QueryClient)\n // ==========================================================================\n\n /**\n * Get the underlying QueryClient (for advanced usage).\n *\n * @returns The underlying QueryClient instance.\n */\n get queryClient(): QueryClient {\n return this.#sharedQueryClient;\n }\n\n /**\n * Get cached data for a query key.\n *\n * @param queryKey - The query key to look up.\n * @returns The cached data or undefined.\n */\n getCachedData<CachedData>(queryKey: QueryKey): CachedData | undefined {\n return this.#sharedQueryClient.getQueryData<CachedData>(queryKey);\n }\n\n /**\n * Set cached data for a query key.\n *\n * @param queryKey - The query key to set data for.\n * @param data - The data to cache.\n */\n setCachedData<CachedData>(queryKey: QueryKey, data: CachedData): void {\n this.#sharedQueryClient.setQueryData(queryKey, data);\n }\n\n /**\n * Check if a query is currently fetching.\n *\n * @param queryKey - The query key to check.\n * @returns True if the query is currently fetching.\n */\n isFetching(queryKey: QueryKey): boolean {\n return this.#sharedQueryClient.isFetching({ queryKey }) > 0;\n }\n\n /**\n * Clear all cached data across all sub-clients.\n */\n clear(): void {\n this.#sharedQueryClient.clear();\n }\n\n /**\n * Invalidate all queries across all sub-clients.\n */\n async invalidateAll(): Promise<void> {\n await this.#sharedQueryClient.invalidateQueries();\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.#sharedQueryClient.resetQueries({\n queryKey: authQueryKeys.bearerToken(),\n });\n }\n}\n\n/**\n * Factory function to create an ApiPlatformClient.\n *\n * @param options - Configuration options for the client.\n * @returns A new ApiPlatformClient instance.\n */\nexport function createApiPlatformClient(\n options: ApiPlatformClientOptions,\n): ApiPlatformClient {\n return new ApiPlatformClient(options);\n}\n"]}
@@ -111,6 +111,9 @@ export declare class ApiPlatformClient {
111
111
  /**
112
112
  * Invalidate the cached auth token.
113
113
  * Call this when the user logs out or the token expires.
114
+ *
115
+ * Uses resetQueries() instead of invalidateQueries() to completely remove
116
+ * the cached value, ensuring the next request fetches a fresh token immediately.
114
117
  */
115
118
  invalidateAuthToken(): Promise<void>;
116
119
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ApiPlatformClient.d.cts","sourceRoot":"","sources":["../../src/api/ApiPlatformClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,WAAW,EAAE,6BAA6B;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,6BAA6B;AAGrD,OAAO,EAAE,iBAAiB,EAAE,6BAAmB;AAC/C,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAQ3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,2BAAuB;AAC/D,OAAO,EAAE,cAAc,EAAE,0BAAgB;AACzC,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAM3C;;;;;;;;;GASG;AACH,qBAAa,iBAAiB;;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IAErC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;gBAOrB,OAAO,EAAE,wBAAwB;IAiC7C;;;;OAIG;IACH,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED;;;;;OAKG;IACH,aAAa,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS;IAIrE;;;;;OAKG;IACH,aAAa,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAIrE;;;;;OAKG;IACH,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO;IAIvC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC;;;OAGG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;CAK3C;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CAEnB"}
1
+ {"version":3,"file":"ApiPlatformClient.d.cts","sourceRoot":"","sources":["../../src/api/ApiPlatformClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,WAAW,EAAE,6BAA6B;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,6BAA6B;AAGrD,OAAO,EAAE,iBAAiB,EAAE,6BAAmB;AAE/C,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAO3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,2BAAuB;AAC/D,OAAO,EAAE,cAAc,EAAE,0BAAgB;AACzC,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAM3C;;;;;;;;;GASG;AACH,qBAAa,iBAAiB;;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IAErC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;gBAOrB,OAAO,EAAE,wBAAwB;IAiC7C;;;;OAIG;IACH,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED;;;;;OAKG;IACH,aAAa,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS;IAIrE;;;;;OAKG;IACH,aAAa,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAIrE;;;;;OAKG;IACH,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO;IAIvC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC;;;;;;OAMG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;CAK3C;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CAEnB"}
@@ -111,6 +111,9 @@ export declare class ApiPlatformClient {
111
111
  /**
112
112
  * Invalidate the cached auth token.
113
113
  * Call this when the user logs out or the token expires.
114
+ *
115
+ * Uses resetQueries() instead of invalidateQueries() to completely remove
116
+ * the cached value, ensuring the next request fetches a fresh token immediately.
114
117
  */
115
118
  invalidateAuthToken(): Promise<void>;
116
119
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ApiPlatformClient.d.mts","sourceRoot":"","sources":["../../src/api/ApiPlatformClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,WAAW,EAAE,6BAA6B;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,6BAA6B;AAGrD,OAAO,EAAE,iBAAiB,EAAE,6BAAmB;AAC/C,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAQ3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,2BAAuB;AAC/D,OAAO,EAAE,cAAc,EAAE,0BAAgB;AACzC,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAM3C;;;;;;;;;GASG;AACH,qBAAa,iBAAiB;;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IAErC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;gBAOrB,OAAO,EAAE,wBAAwB;IAiC7C;;;;OAIG;IACH,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED;;;;;OAKG;IACH,aAAa,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS;IAIrE;;;;;OAKG;IACH,aAAa,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAIrE;;;;;OAKG;IACH,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO;IAIvC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC;;;OAGG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;CAK3C;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CAEnB"}
1
+ {"version":3,"file":"ApiPlatformClient.d.mts","sourceRoot":"","sources":["../../src/api/ApiPlatformClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,WAAW,EAAE,6BAA6B;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,6BAA6B;AAGrD,OAAO,EAAE,iBAAiB,EAAE,6BAAmB;AAE/C,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAO3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,2BAAuB;AAC/D,OAAO,EAAE,cAAc,EAAE,0BAAgB;AACzC,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAM3C;;;;;;;;;GASG;AACH,qBAAa,iBAAiB;;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IAErC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;gBAOrB,OAAO,EAAE,wBAAwB;IAiC7C;;;;OAIG;IACH,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED;;;;;OAKG;IACH,aAAa,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS;IAIrE;;;;;OAKG;IACH,aAAa,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAIrE;;;;;OAKG;IACH,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO;IAIvC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC;;;;;;OAMG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;CAK3C;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CAEnB"}
@@ -48,8 +48,9 @@ var _ApiPlatformClient_sharedQueryClient;
48
48
  import { QueryClient } from "@tanstack/query-core";
49
49
  // Import API clients from subfolders
50
50
  import { AccountsApiClient } from "./accounts/index.mjs";
51
+ import { authQueryKeys } from "./base-client.mjs";
51
52
  import { PricesApiClient } from "./prices/index.mjs";
52
- import { STALE_TIMES, GC_TIMES, authQueryKeys, shouldRetry, calculateRetryDelay } from "./shared-types.mjs";
53
+ import { STALE_TIMES, GC_TIMES, shouldRetry, calculateRetryDelay } from "./shared-types.mjs";
53
54
  import { TokenApiClient } from "./token/index.mjs";
54
55
  import { TokensApiClient } from "./tokens/index.mjs";
55
56
  // ============================================================================
@@ -148,9 +149,12 @@ export class ApiPlatformClient {
148
149
  /**
149
150
  * Invalidate the cached auth token.
150
151
  * Call this when the user logs out or the token expires.
152
+ *
153
+ * Uses resetQueries() instead of invalidateQueries() to completely remove
154
+ * the cached value, ensuring the next request fetches a fresh token immediately.
151
155
  */
152
156
  async invalidateAuthToken() {
153
- await __classPrivateFieldGet(this, _ApiPlatformClient_sharedQueryClient, "f").invalidateQueries({
157
+ await __classPrivateFieldGet(this, _ApiPlatformClient_sharedQueryClient, "f").resetQueries({
154
158
  queryKey: authQueryKeys.bearerToken(),
155
159
  });
156
160
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ApiPlatformClient.mjs","sourceRoot":"","sources":["../../src/api/ApiPlatformClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;;;;;;;;;;;;;AAEH,OAAO,EAAE,WAAW,EAAE,6BAA6B;AAGnD,qCAAqC;AACrC,OAAO,EAAE,iBAAiB,EAAE,6BAAmB;AAC/C,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAC3C,OAAO,EACL,WAAW,EACX,QAAQ,EACR,aAAa,EACb,WAAW,EACX,mBAAmB,EACpB,2BAAuB;AAExB,OAAO,EAAE,cAAc,EAAE,0BAAgB;AACzC,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAE3C,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E;;;;;;;;;GASG;AACH,MAAM,OAAO,iBAAiB;IA8B5B,YAAY,OAAiC;QAL7C;;WAEG;QACM,uDAAgC;QAGvC,iEAAiE;QACjE,uBAAA,IAAI,wCACF,OAAO,CAAC,WAAW;YACnB,IAAI,WAAW,CAAC;gBACd,cAAc,EAAE;oBACd,OAAO,EAAE;wBACP,SAAS,EAAE,WAAW,CAAC,OAAO;wBAC9B,MAAM,EAAE,QAAQ,CAAC,OAAO;wBACxB,KAAK,EAAE,WAAW;wBAClB,UAAU,EAAE,mBAAmB;wBAC/B,oBAAoB,EAAE,KAAK;wBAC3B,WAAW,EAAE,QAAQ;qBACtB;iBACF;aACF,CAAC,MAAA,CAAC;QAEL,iDAAiD;QACjD,MAAM,aAAa,GAA6B;YAC9C,GAAG,OAAO;YACV,WAAW,EAAE,uBAAA,IAAI,4CAAmB;SACrC,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,IAAI,iBAAiB,CAAC,aAAa,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,CAAC,aAAa,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,GAAG,IAAI,cAAc,CAAC,aAAa,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,CAAC,aAAa,CAAC,CAAC;IACnD,CAAC;IAED,6EAA6E;IAC7E,oDAAoD;IACpD,6EAA6E;IAE7E;;;;OAIG;IACH,IAAI,WAAW;QACb,OAAO,uBAAA,IAAI,4CAAmB,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAa,QAAkB;QAC1C,OAAO,uBAAA,IAAI,4CAAmB,CAAC,YAAY,CAAa,QAAQ,CAAC,CAAC;IACpE,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAa,QAAkB,EAAE,IAAgB;QAC5D,uBAAA,IAAI,4CAAmB,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,QAAkB;QAC3B,OAAO,uBAAA,IAAI,4CAAmB,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACH,KAAK;QACH,uBAAA,IAAI,4CAAmB,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa;QACjB,MAAM,uBAAA,IAAI,4CAAmB,CAAC,iBAAiB,EAAE,CAAC;IACpD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,mBAAmB;QACvB,MAAM,uBAAA,IAAI,4CAAmB,CAAC,iBAAiB,CAAC;YAC9C,QAAQ,EAAE,aAAa,CAAC,WAAW,EAAE;SACtC,CAAC,CAAC;IACL,CAAC;CACF;;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAiC;IAEjC,OAAO,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC","sourcesContent":["/**\n * ApiPlatformClient - MetaMask API Platform Client\n *\n * A comprehensive API client that uses @tanstack/query-core directly for:\n * - Automatic request deduplication\n * - Intelligent caching\n * - Automatic retries with exponential backoff\n *\n * Provides unified access to all MetaMask backend APIs:\n * - Accounts API (accounts.api.cx.metamask.io)\n * - Price API (price.api.cx.metamask.io)\n * - Token API (token.api.cx.metamask.io)\n * - Tokens API (tokens.api.cx.metamask.io)\n *\n * @example\n * ```typescript\n * const client = new ApiPlatformClient({\n * clientProduct: 'metamask-extension',\n * getBearerToken: async () => token,\n * });\n *\n * // Access API methods through sub-clients\n * const networks = await client.accounts.fetchV2SupportedNetworks();\n * const balances = await client.accounts.fetchV5MultiAccountBalances(accountIds);\n * const prices = await client.prices.fetchV3SpotPrices(assetIds);\n * const tokenList = await client.token.fetchTokenList(1);\n * const assets = await client.tokens.fetchV3Assets(assetIds);\n *\n * // Cache management\n * await client.invalidateAll(); // Invalidate all caches\n * await client.invalidateAuthToken(); // Invalidate auth token\n * await client.accounts.invalidateBalances(); // Domain-specific via sub-client\n * await client.prices.invalidatePrices(); // Domain-specific via sub-client\n * ```\n */\n\nimport { QueryClient } from '@tanstack/query-core';\nimport type { QueryKey } from '@tanstack/query-core';\n\n// Import API clients from subfolders\nimport { AccountsApiClient } from './accounts';\nimport { PricesApiClient } from './prices';\nimport {\n STALE_TIMES,\n GC_TIMES,\n authQueryKeys,\n shouldRetry,\n calculateRetryDelay,\n} from './shared-types';\nimport type { ApiPlatformClientOptions } from './shared-types';\nimport { TokenApiClient } from './token';\nimport { TokensApiClient } from './tokens';\n\n// ============================================================================\n// UNIFIED API CLIENT\n// ============================================================================\n\n/**\n * MetaMask API Platform Client with TanStack Query caching.\n * Provides cached access to all MetaMask backend APIs through a unified interface.\n *\n * Access API methods through the sub-clients:\n * - `client.accounts` - Accounts API (balances, transactions, NFTs, etc.)\n * - `client.prices` - Prices API (spot prices, exchange rates, historical prices)\n * - `client.token` - Token API (token metadata, trending, top gainers)\n * - `client.tokens` - Tokens API (bulk asset operations, supported networks)\n */\nexport class ApiPlatformClient {\n /**\n * Accounts API client.\n * Provides methods for balances, transactions, relationships, NFTs, and token discovery.\n */\n readonly accounts: AccountsApiClient;\n\n /**\n * Prices API client.\n * Provides methods for spot prices, exchange rates, and historical prices.\n */\n readonly prices: PricesApiClient;\n\n /**\n * Token API client.\n * Provides methods for token metadata, networks, trending tokens, and top assets.\n */\n readonly token: TokenApiClient;\n\n /**\n * Tokens API client.\n * Provides methods for bulk asset operations and supported networks.\n */\n readonly tokens: TokensApiClient;\n\n /**\n * Shared QueryClient instance used by all sub-clients.\n */\n readonly #sharedQueryClient: QueryClient;\n\n constructor(options: ApiPlatformClientOptions) {\n // Create or use provided QueryClient - shared by all sub-clients\n this.#sharedQueryClient =\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 // Pass the shared QueryClient to all sub-clients\n const sharedOptions: ApiPlatformClientOptions = {\n ...options,\n queryClient: this.#sharedQueryClient,\n };\n\n this.accounts = new AccountsApiClient(sharedOptions);\n this.prices = new PricesApiClient(sharedOptions);\n this.token = new TokenApiClient(sharedOptions);\n this.tokens = new TokensApiClient(sharedOptions);\n }\n\n // ==========================================================================\n // CACHE MANAGEMENT (operates on shared QueryClient)\n // ==========================================================================\n\n /**\n * Get the underlying QueryClient (for advanced usage).\n *\n * @returns The underlying QueryClient instance.\n */\n get queryClient(): QueryClient {\n return this.#sharedQueryClient;\n }\n\n /**\n * Get cached data for a query key.\n *\n * @param queryKey - The query key to look up.\n * @returns The cached data or undefined.\n */\n getCachedData<CachedData>(queryKey: QueryKey): CachedData | undefined {\n return this.#sharedQueryClient.getQueryData<CachedData>(queryKey);\n }\n\n /**\n * Set cached data for a query key.\n *\n * @param queryKey - The query key to set data for.\n * @param data - The data to cache.\n */\n setCachedData<CachedData>(queryKey: QueryKey, data: CachedData): void {\n this.#sharedQueryClient.setQueryData(queryKey, data);\n }\n\n /**\n * Check if a query is currently fetching.\n *\n * @param queryKey - The query key to check.\n * @returns True if the query is currently fetching.\n */\n isFetching(queryKey: QueryKey): boolean {\n return this.#sharedQueryClient.isFetching({ queryKey }) > 0;\n }\n\n /**\n * Clear all cached data across all sub-clients.\n */\n clear(): void {\n this.#sharedQueryClient.clear();\n }\n\n /**\n * Invalidate all queries across all sub-clients.\n */\n async invalidateAll(): Promise<void> {\n await this.#sharedQueryClient.invalidateQueries();\n }\n\n /**\n * Invalidate the cached auth token.\n * Call this when the user logs out or the token expires.\n */\n async invalidateAuthToken(): Promise<void> {\n await this.#sharedQueryClient.invalidateQueries({\n queryKey: authQueryKeys.bearerToken(),\n });\n }\n}\n\n/**\n * Factory function to create an ApiPlatformClient.\n *\n * @param options - Configuration options for the client.\n * @returns A new ApiPlatformClient instance.\n */\nexport function createApiPlatformClient(\n options: ApiPlatformClientOptions,\n): ApiPlatformClient {\n return new ApiPlatformClient(options);\n}\n"]}
1
+ {"version":3,"file":"ApiPlatformClient.mjs","sourceRoot":"","sources":["../../src/api/ApiPlatformClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;;;;;;;;;;;;;AAEH,OAAO,EAAE,WAAW,EAAE,6BAA6B;AAGnD,qCAAqC;AACrC,OAAO,EAAE,iBAAiB,EAAE,6BAAmB;AAC/C,OAAO,EAAE,aAAa,EAAE,0BAAsB;AAC9C,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAC3C,OAAO,EACL,WAAW,EACX,QAAQ,EACR,WAAW,EACX,mBAAmB,EACpB,2BAAuB;AAExB,OAAO,EAAE,cAAc,EAAE,0BAAgB;AACzC,OAAO,EAAE,eAAe,EAAE,2BAAiB;AAE3C,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E;;;;;;;;;GASG;AACH,MAAM,OAAO,iBAAiB;IA8B5B,YAAY,OAAiC;QAL7C;;WAEG;QACM,uDAAgC;QAGvC,iEAAiE;QACjE,uBAAA,IAAI,wCACF,OAAO,CAAC,WAAW;YACnB,IAAI,WAAW,CAAC;gBACd,cAAc,EAAE;oBACd,OAAO,EAAE;wBACP,SAAS,EAAE,WAAW,CAAC,OAAO;wBAC9B,MAAM,EAAE,QAAQ,CAAC,OAAO;wBACxB,KAAK,EAAE,WAAW;wBAClB,UAAU,EAAE,mBAAmB;wBAC/B,oBAAoB,EAAE,KAAK;wBAC3B,WAAW,EAAE,QAAQ;qBACtB;iBACF;aACF,CAAC,MAAA,CAAC;QAEL,iDAAiD;QACjD,MAAM,aAAa,GAA6B;YAC9C,GAAG,OAAO;YACV,WAAW,EAAE,uBAAA,IAAI,4CAAmB;SACrC,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,IAAI,iBAAiB,CAAC,aAAa,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,CAAC,aAAa,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,GAAG,IAAI,cAAc,CAAC,aAAa,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,CAAC,aAAa,CAAC,CAAC;IACnD,CAAC;IAED,6EAA6E;IAC7E,oDAAoD;IACpD,6EAA6E;IAE7E;;;;OAIG;IACH,IAAI,WAAW;QACb,OAAO,uBAAA,IAAI,4CAAmB,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAa,QAAkB;QAC1C,OAAO,uBAAA,IAAI,4CAAmB,CAAC,YAAY,CAAa,QAAQ,CAAC,CAAC;IACpE,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAa,QAAkB,EAAE,IAAgB;QAC5D,uBAAA,IAAI,4CAAmB,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,QAAkB;QAC3B,OAAO,uBAAA,IAAI,4CAAmB,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACH,KAAK;QACH,uBAAA,IAAI,4CAAmB,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa;QACjB,MAAM,uBAAA,IAAI,4CAAmB,CAAC,iBAAiB,EAAE,CAAC;IACpD,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,mBAAmB;QACvB,MAAM,uBAAA,IAAI,4CAAmB,CAAC,YAAY,CAAC;YACzC,QAAQ,EAAE,aAAa,CAAC,WAAW,EAAE;SACtC,CAAC,CAAC;IACL,CAAC;CACF;;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAiC;IAEjC,OAAO,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC","sourcesContent":["/**\n * ApiPlatformClient - MetaMask API Platform Client\n *\n * A comprehensive API client that uses @tanstack/query-core directly for:\n * - Automatic request deduplication\n * - Intelligent caching\n * - Automatic retries with exponential backoff\n *\n * Provides unified access to all MetaMask backend APIs:\n * - Accounts API (accounts.api.cx.metamask.io)\n * - Price API (price.api.cx.metamask.io)\n * - Token API (token.api.cx.metamask.io)\n * - Tokens API (tokens.api.cx.metamask.io)\n *\n * @example\n * ```typescript\n * const client = new ApiPlatformClient({\n * clientProduct: 'metamask-extension',\n * getBearerToken: async () => token,\n * });\n *\n * // Access API methods through sub-clients\n * const networks = await client.accounts.fetchV2SupportedNetworks();\n * const balances = await client.accounts.fetchV5MultiAccountBalances(accountIds);\n * const prices = await client.prices.fetchV3SpotPrices(assetIds);\n * const tokenList = await client.token.fetchTokenList(1);\n * const assets = await client.tokens.fetchV3Assets(assetIds);\n *\n * // Cache management\n * await client.invalidateAll(); // Invalidate all caches\n * await client.invalidateAuthToken(); // Invalidate auth token\n * await client.accounts.invalidateBalances(); // Domain-specific via sub-client\n * await client.prices.invalidatePrices(); // Domain-specific via sub-client\n * ```\n */\n\nimport { QueryClient } from '@tanstack/query-core';\nimport type { QueryKey } from '@tanstack/query-core';\n\n// Import API clients from subfolders\nimport { AccountsApiClient } from './accounts';\nimport { authQueryKeys } from './base-client';\nimport { PricesApiClient } from './prices';\nimport {\n STALE_TIMES,\n GC_TIMES,\n shouldRetry,\n calculateRetryDelay,\n} from './shared-types';\nimport type { ApiPlatformClientOptions } from './shared-types';\nimport { TokenApiClient } from './token';\nimport { TokensApiClient } from './tokens';\n\n// ============================================================================\n// UNIFIED API CLIENT\n// ============================================================================\n\n/**\n * MetaMask API Platform Client with TanStack Query caching.\n * Provides cached access to all MetaMask backend APIs through a unified interface.\n *\n * Access API methods through the sub-clients:\n * - `client.accounts` - Accounts API (balances, transactions, NFTs, etc.)\n * - `client.prices` - Prices API (spot prices, exchange rates, historical prices)\n * - `client.token` - Token API (token metadata, trending, top gainers)\n * - `client.tokens` - Tokens API (bulk asset operations, supported networks)\n */\nexport class ApiPlatformClient {\n /**\n * Accounts API client.\n * Provides methods for balances, transactions, relationships, NFTs, and token discovery.\n */\n readonly accounts: AccountsApiClient;\n\n /**\n * Prices API client.\n * Provides methods for spot prices, exchange rates, and historical prices.\n */\n readonly prices: PricesApiClient;\n\n /**\n * Token API client.\n * Provides methods for token metadata, networks, trending tokens, and top assets.\n */\n readonly token: TokenApiClient;\n\n /**\n * Tokens API client.\n * Provides methods for bulk asset operations and supported networks.\n */\n readonly tokens: TokensApiClient;\n\n /**\n * Shared QueryClient instance used by all sub-clients.\n */\n readonly #sharedQueryClient: QueryClient;\n\n constructor(options: ApiPlatformClientOptions) {\n // Create or use provided QueryClient - shared by all sub-clients\n this.#sharedQueryClient =\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 // Pass the shared QueryClient to all sub-clients\n const sharedOptions: ApiPlatformClientOptions = {\n ...options,\n queryClient: this.#sharedQueryClient,\n };\n\n this.accounts = new AccountsApiClient(sharedOptions);\n this.prices = new PricesApiClient(sharedOptions);\n this.token = new TokenApiClient(sharedOptions);\n this.tokens = new TokensApiClient(sharedOptions);\n }\n\n // ==========================================================================\n // CACHE MANAGEMENT (operates on shared QueryClient)\n // ==========================================================================\n\n /**\n * Get the underlying QueryClient (for advanced usage).\n *\n * @returns The underlying QueryClient instance.\n */\n get queryClient(): QueryClient {\n return this.#sharedQueryClient;\n }\n\n /**\n * Get cached data for a query key.\n *\n * @param queryKey - The query key to look up.\n * @returns The cached data or undefined.\n */\n getCachedData<CachedData>(queryKey: QueryKey): CachedData | undefined {\n return this.#sharedQueryClient.getQueryData<CachedData>(queryKey);\n }\n\n /**\n * Set cached data for a query key.\n *\n * @param queryKey - The query key to set data for.\n * @param data - The data to cache.\n */\n setCachedData<CachedData>(queryKey: QueryKey, data: CachedData): void {\n this.#sharedQueryClient.setQueryData(queryKey, data);\n }\n\n /**\n * Check if a query is currently fetching.\n *\n * @param queryKey - The query key to check.\n * @returns True if the query is currently fetching.\n */\n isFetching(queryKey: QueryKey): boolean {\n return this.#sharedQueryClient.isFetching({ queryKey }) > 0;\n }\n\n /**\n * Clear all cached data across all sub-clients.\n */\n clear(): void {\n this.#sharedQueryClient.clear();\n }\n\n /**\n * Invalidate all queries across all sub-clients.\n */\n async invalidateAll(): Promise<void> {\n await this.#sharedQueryClient.invalidateQueries();\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.#sharedQueryClient.resetQueries({\n queryKey: authQueryKeys.bearerToken(),\n });\n }\n}\n\n/**\n * Factory function to create an ApiPlatformClient.\n *\n * @param options - Configuration options for the client.\n * @returns A new ApiPlatformClient instance.\n */\nexport function createApiPlatformClient(\n options: ApiPlatformClientOptions,\n): ApiPlatformClient {\n return new ApiPlatformClient(options);\n}\n"]}
@@ -15,13 +15,17 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
15
15
  };
16
16
  var _BaseApiClient_queryClientInstance;
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.HttpError = exports.GC_TIMES = exports.STALE_TIMES = exports.API_URLS = exports.BaseApiClient = void 0;
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");
20
20
  const shared_types_1 = require("./shared-types.cjs");
21
21
  Object.defineProperty(exports, "API_URLS", { enumerable: true, get: function () { return shared_types_1.API_URLS; } });
22
22
  Object.defineProperty(exports, "STALE_TIMES", { enumerable: true, get: function () { return shared_types_1.STALE_TIMES; } });
23
23
  Object.defineProperty(exports, "GC_TIMES", { enumerable: true, get: function () { return shared_types_1.GC_TIMES; } });
24
24
  Object.defineProperty(exports, "HttpError", { enumerable: true, get: function () { return shared_types_1.HttpError; } });
25
+ // Auth query keys - shared for token management across clients
26
+ exports.authQueryKeys = {
27
+ bearerToken: () => ['auth', 'bearerToken'],
28
+ };
25
29
  /**
26
30
  * Base API Client with shared HTTP and caching functionality.
27
31
  * Extended by all specific API clients.
@@ -36,6 +40,18 @@ class BaseApiClient {
36
40
  get queryClient() {
37
41
  return __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f");
38
42
  }
43
+ /**
44
+ * Invalidate the cached auth token.
45
+ * Call this when the user logs out or the token expires.
46
+ *
47
+ * Uses resetQueries() instead of invalidateQueries() to completely remove
48
+ * the cached value, ensuring the next request fetches a fresh token immediately.
49
+ */
50
+ async invalidateAuthToken() {
51
+ await __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f").resetQueries({
52
+ queryKey: exports.authQueryKeys.bearerToken(),
53
+ });
54
+ }
39
55
  constructor(options) {
40
56
  _BaseApiClient_queryClientInstance.set(this, void 0);
41
57
  this.clientProduct = options.clientProduct;
@@ -84,19 +100,31 @@ class BaseApiClient {
84
100
  'X-Client-Product': this.clientProduct,
85
101
  'X-Client-Version': this.clientVersion,
86
102
  };
87
- // Use TanStack Query to cache the bearer token
88
- // Wrap getBearerToken to return null instead of undefined (TanStack Query doesn't allow undefined)
103
+ // Get bearer token using fetchQuery for automatic deduplication
89
104
  if (this.getBearerToken) {
105
+ const queryKey = exports.authQueryKeys.bearerToken();
90
106
  const { getBearerToken } = this;
91
- const token = await __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f").fetchQuery({
92
- queryKey: shared_types_1.authQueryKeys.bearerToken(),
93
- queryFn: async () => (await getBearerToken()) ?? null,
94
- staleTime: shared_types_1.STALE_TIMES.AUTH_TOKEN,
95
- gcTime: shared_types_1.GC_TIMES.DEFAULT,
96
- });
97
- if (token) {
107
+ try {
108
+ // fetchQuery handles caching and deduplicates concurrent requests
109
+ const token = await __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f").fetchQuery({
110
+ queryKey,
111
+ queryFn: async () => {
112
+ const result = await getBearerToken();
113
+ // Throw if no token - prevents caching null/undefined
114
+ // so subsequent requests can retry (e.g., after user logs in)
115
+ if (!result) {
116
+ throw new Error('No bearer token available');
117
+ }
118
+ return result;
119
+ },
120
+ staleTime: shared_types_1.STALE_TIMES.AUTH_TOKEN,
121
+ retry: false, // Don't retry auth failures
122
+ });
98
123
  headers.Authorization = `Bearer ${token}`;
99
124
  }
125
+ catch {
126
+ // No token available - continue without auth header
127
+ }
100
128
  }
101
129
  const response = await fetch(url.toString(), {
102
130
  method: 'GET',
@@ -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';\n\nimport {\n API_URLS,\n STALE_TIMES,\n GC_TIMES,\n authQueryKeys,\n calculateRetryDelay,\n shouldRetry,\n HttpError,\n} from './shared-types';\nimport type { ApiPlatformClientOptions } from './shared-types';\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 constructor(options: ApiPlatformClientOptions) {\n this.clientProduct = options.clientProduct;\n this.clientVersion = options.clientVersion ?? '1.0.0';\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-Client-Product': this.clientProduct,\n 'X-Client-Version': this.clientVersion,\n };\n\n // Use TanStack Query to cache the bearer token\n // Wrap getBearerToken to return null instead of undefined (TanStack Query doesn't allow undefined)\n if (this.getBearerToken) {\n const { getBearerToken } = this;\n const token = await this.#queryClientInstance.fetchQuery({\n queryKey: authQueryKeys.bearerToken(),\n queryFn: async () => (await getBearerToken()) ?? null,\n staleTime: STALE_TIMES.AUTH_TOKEN,\n gcTime: GC_TIMES.DEFAULT,\n });\n if (token) {\n headers.Authorization = `Bearer ${token}`;\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,qDAOwB;AAwKf,yFA9KP,uBAAQ,OA8KO;AAAE,4FA7KjB,0BAAW,OA6KiB;AAAE,yFA5K9B,uBAAQ,OA4K8B;AAAE,0FAzKxC,wBAAS,OAyKwC;AArKnD,+DAA+D;AAClD,QAAA,aAAa,GAAG;IAC3B,WAAW,EAAE,GAAa,EAAE,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC;CAC5C,CAAC;AAeX;;;GAGG;AACH,MAAa,aAAa;IASxB;;;;;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,IAAI,OAAO,CAAC;QACtD,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAE7C,uBAAA,IAAI,sCACF,OAAO,CAAC,WAAW;YACnB,IAAI,wBAAW,CAAC;gBACd,cAAc,EAAE;oBACd,OAAO,EAAE;wBACP,SAAS,EAAE,0BAAW,CAAC,OAAO;wBAC9B,MAAM,EAAE,uBAAQ,CAAC,OAAO;wBACxB,KAAK,EAAE,0BAAW;wBAClB,UAAU,EAAE,kCAAmB;wBAC/B,oBAAoB,EAAE,KAAK;wBAC3B,WAAW,EAAE,QAAQ;qBACtB;iBACF;aACF,CAAC,MAAA,CAAC;IACP,CAAC;IAED;;;;;;;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,kBAAkB,EAAE,IAAI,CAAC,aAAa;YACtC,kBAAkB,EAAE,IAAI,CAAC,aAAa;SACvC,CAAC;QAEF,gEAAgE;QAChE,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,qBAAa,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;YAEhC,IAAI,CAAC;gBACH,kEAAkE;gBAClE,MAAM,KAAK,GAAG,MAAM,uBAAA,IAAI,0CAAqB,CAAC,UAAU,CAAC;oBACvD,QAAQ;oBACR,OAAO,EAAE,KAAK,IAAI,EAAE;wBAClB,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;wBACtC,sDAAsD;wBACtD,8DAA8D;wBAC9D,IAAI,CAAC,MAAM,EAAE,CAAC;4BACZ,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;wBAC/C,CAAC;wBACD,OAAO,MAAM,CAAC;oBAChB,CAAC;oBACD,SAAS,EAAE,0BAAW,CAAC,UAAU;oBACjC,KAAK,EAAE,KAAK,EAAE,4BAA4B;iBAC3C,CAAC,CAAC;gBAEH,OAAO,CAAC,aAAa,GAAG,UAAU,KAAK,EAAE,CAAC;YAC5C,CAAC;YAAC,MAAM,CAAC;gBACP,oDAAoD;YACtD,CAAC;QACH,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,wBAAS,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;AA5ID,sCA4IC","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';\nimport type { ApiPlatformClientOptions } from './shared-types';\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 ?? '1.0.0';\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-Client-Product': this.clientProduct,\n 'X-Client-Version': 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"]}
@@ -4,6 +4,9 @@
4
4
  import { QueryClient } from "@tanstack/query-core";
5
5
  import { API_URLS, STALE_TIMES, GC_TIMES, HttpError } from "./shared-types.cjs";
6
6
  import type { ApiPlatformClientOptions } from "./shared-types.cjs";
7
+ export declare const authQueryKeys: {
8
+ readonly bearerToken: () => readonly unknown[];
9
+ };
7
10
  export type { ApiPlatformClientOptions };
8
11
  /**
9
12
  * Internal fetch options for HTTP requests.
@@ -28,6 +31,14 @@ export declare class BaseApiClient {
28
31
  * @returns The QueryClient instance.
29
32
  */
30
33
  get queryClient(): QueryClient;
34
+ /**
35
+ * Invalidate the cached auth token.
36
+ * Call this when the user logs out or the token expires.
37
+ *
38
+ * Uses resetQueries() instead of invalidateQueries() to completely remove
39
+ * the cached value, ensuring the next request fetches a fresh token immediately.
40
+ */
41
+ invalidateAuthToken(): Promise<void>;
31
42
  constructor(options: ApiPlatformClientOptions);
32
43
  /**
33
44
  * Internal HTTP fetch method with authentication and error handling.
@@ -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;AAEnD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EAIR,SAAS,EACV,2BAAuB;AACxB,OAAO,KAAK,EAAE,wBAAwB,EAAE,2BAAuB;AAE/D,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,EAAE,MAAM,CAAC;IAEzC,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAItE;;;;;OAKG;IACH,IAAI,WAAW,IAAI,WAAW,CAE7B;gBAEW,OAAO,EAAE,wBAAwB;IAqB7C;;;;;;;OAOG;cACa,KAAK,CAAC,YAAY,EAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,YAAY,CAAC;CA8DzB;AAGD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC"}
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,EAGR,SAAS,EACV,2BAAuB;AACxB,OAAO,KAAK,EAAE,wBAAwB,EAAE,2BAAuB;AAG/D,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,EAAE,MAAM,CAAC;IAEzC,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAItE;;;;;OAKG;IACH,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED;;;;;;OAMG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;gBAM9B,OAAO,EAAE,wBAAwB;IAqB7C;;;;;;;OAOG;cACa,KAAK,CAAC,YAAY,EAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,YAAY,CAAC;CA2EzB;AAGD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC"}
@@ -4,6 +4,9 @@
4
4
  import { QueryClient } from "@tanstack/query-core";
5
5
  import { API_URLS, STALE_TIMES, GC_TIMES, HttpError } from "./shared-types.mjs";
6
6
  import type { ApiPlatformClientOptions } from "./shared-types.mjs";
7
+ export declare const authQueryKeys: {
8
+ readonly bearerToken: () => readonly unknown[];
9
+ };
7
10
  export type { ApiPlatformClientOptions };
8
11
  /**
9
12
  * Internal fetch options for HTTP requests.
@@ -28,6 +31,14 @@ export declare class BaseApiClient {
28
31
  * @returns The QueryClient instance.
29
32
  */
30
33
  get queryClient(): QueryClient;
34
+ /**
35
+ * Invalidate the cached auth token.
36
+ * Call this when the user logs out or the token expires.
37
+ *
38
+ * Uses resetQueries() instead of invalidateQueries() to completely remove
39
+ * the cached value, ensuring the next request fetches a fresh token immediately.
40
+ */
41
+ invalidateAuthToken(): Promise<void>;
31
42
  constructor(options: ApiPlatformClientOptions);
32
43
  /**
33
44
  * Internal HTTP fetch method with authentication and error handling.
@@ -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;AAEnD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EAIR,SAAS,EACV,2BAAuB;AACxB,OAAO,KAAK,EAAE,wBAAwB,EAAE,2BAAuB;AAE/D,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,EAAE,MAAM,CAAC;IAEzC,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAItE;;;;;OAKG;IACH,IAAI,WAAW,IAAI,WAAW,CAE7B;gBAEW,OAAO,EAAE,wBAAwB;IAqB7C;;;;;;;OAOG;cACa,KAAK,CAAC,YAAY,EAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,YAAY,CAAC;CA8DzB;AAGD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC"}
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,EAGR,SAAS,EACV,2BAAuB;AACxB,OAAO,KAAK,EAAE,wBAAwB,EAAE,2BAAuB;AAG/D,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,EAAE,MAAM,CAAC;IAEzC,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAItE;;;;;OAKG;IACH,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED;;;;;;OAMG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;gBAM9B,OAAO,EAAE,wBAAwB;IAqB7C;;;;;;;OAOG;cACa,KAAK,CAAC,YAAY,EAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,YAAY,CAAC;CA2EzB;AAGD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC"}
@@ -14,7 +14,11 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
14
14
  };
15
15
  var _BaseApiClient_queryClientInstance;
16
16
  import { QueryClient } from "@tanstack/query-core";
17
- import { API_URLS, STALE_TIMES, GC_TIMES, authQueryKeys, calculateRetryDelay, shouldRetry, HttpError } from "./shared-types.mjs";
17
+ import { API_URLS, STALE_TIMES, GC_TIMES, calculateRetryDelay, shouldRetry, HttpError } from "./shared-types.mjs";
18
+ // Auth query keys - shared for token management across clients
19
+ export const authQueryKeys = {
20
+ bearerToken: () => ['auth', 'bearerToken'],
21
+ };
18
22
  /**
19
23
  * Base API Client with shared HTTP and caching functionality.
20
24
  * Extended by all specific API clients.
@@ -29,6 +33,18 @@ export class BaseApiClient {
29
33
  get queryClient() {
30
34
  return __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f");
31
35
  }
36
+ /**
37
+ * Invalidate the cached auth token.
38
+ * Call this when the user logs out or the token expires.
39
+ *
40
+ * Uses resetQueries() instead of invalidateQueries() to completely remove
41
+ * the cached value, ensuring the next request fetches a fresh token immediately.
42
+ */
43
+ async invalidateAuthToken() {
44
+ await __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f").resetQueries({
45
+ queryKey: authQueryKeys.bearerToken(),
46
+ });
47
+ }
32
48
  constructor(options) {
33
49
  _BaseApiClient_queryClientInstance.set(this, void 0);
34
50
  this.clientProduct = options.clientProduct;
@@ -77,19 +93,31 @@ export class BaseApiClient {
77
93
  'X-Client-Product': this.clientProduct,
78
94
  'X-Client-Version': this.clientVersion,
79
95
  };
80
- // Use TanStack Query to cache the bearer token
81
- // Wrap getBearerToken to return null instead of undefined (TanStack Query doesn't allow undefined)
96
+ // Get bearer token using fetchQuery for automatic deduplication
82
97
  if (this.getBearerToken) {
98
+ const queryKey = authQueryKeys.bearerToken();
83
99
  const { getBearerToken } = this;
84
- const token = await __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f").fetchQuery({
85
- queryKey: authQueryKeys.bearerToken(),
86
- queryFn: async () => (await getBearerToken()) ?? null,
87
- staleTime: STALE_TIMES.AUTH_TOKEN,
88
- gcTime: GC_TIMES.DEFAULT,
89
- });
90
- if (token) {
100
+ try {
101
+ // fetchQuery handles caching and deduplicates concurrent requests
102
+ const token = await __classPrivateFieldGet(this, _BaseApiClient_queryClientInstance, "f").fetchQuery({
103
+ queryKey,
104
+ queryFn: async () => {
105
+ const result = await getBearerToken();
106
+ // Throw if no token - prevents caching null/undefined
107
+ // so subsequent requests can retry (e.g., after user logs in)
108
+ if (!result) {
109
+ throw new Error('No bearer token available');
110
+ }
111
+ return result;
112
+ },
113
+ staleTime: STALE_TIMES.AUTH_TOKEN,
114
+ retry: false, // Don't retry auth failures
115
+ });
91
116
  headers.Authorization = `Bearer ${token}`;
92
117
  }
118
+ catch {
119
+ // No token available - continue without auth header
120
+ }
93
121
  }
94
122
  const response = await fetch(url.toString(), {
95
123
  method: 'GET',
@@ -1 +1 @@
1
- {"version":3,"file":"base-client.mjs","sourceRoot":"","sources":["../../src/api/base-client.ts"],"names":[],"mappings":"AAAA;;GAEG;;;;;;;;;;;;;AAEH,OAAO,EAAE,WAAW,EAAE,6BAA6B;AAEnD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,aAAa,EACb,mBAAmB,EACnB,WAAW,EACX,SAAS,EACV,2BAAuB;AAgBxB;;;GAGG;AACH,MAAM,OAAO,aAAa;IASxB;;;;;OAKG;IACH,IAAI,WAAW;QACb,OAAO,uBAAA,IAAI,0CAAqB,CAAC;IACnC,CAAC;IAED,YAAY,OAAiC;QAZpC,qDAAkC;QAazC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC;QACtD,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAE7C,uBAAA,IAAI,sCACF,OAAO,CAAC,WAAW;YACnB,IAAI,WAAW,CAAC;gBACd,cAAc,EAAE;oBACd,OAAO,EAAE;wBACP,SAAS,EAAE,WAAW,CAAC,OAAO;wBAC9B,MAAM,EAAE,QAAQ,CAAC,OAAO;wBACxB,KAAK,EAAE,WAAW;wBAClB,UAAU,EAAE,mBAAmB;wBAC/B,oBAAoB,EAAE,KAAK;wBAC3B,WAAW,EAAE,QAAQ;qBACtB;iBACF;aACF,CAAC,MAAA,CAAC;IACP,CAAC;IAED;;;;;;;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,kBAAkB,EAAE,IAAI,CAAC,aAAa;YACtC,kBAAkB,EAAE,IAAI,CAAC,aAAa;SACvC,CAAC;QAEF,+CAA+C;QAC/C,mGAAmG;QACnG,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;YAChC,MAAM,KAAK,GAAG,MAAM,uBAAA,IAAI,0CAAqB,CAAC,UAAU,CAAC;gBACvD,QAAQ,EAAE,aAAa,CAAC,WAAW,EAAE;gBACrC,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,cAAc,EAAE,CAAC,IAAI,IAAI;gBACrD,SAAS,EAAE,WAAW,CAAC,UAAU;gBACjC,MAAM,EAAE,QAAQ,CAAC,OAAO;aACzB,CAAC,CAAC;YACH,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,aAAa,GAAG,UAAU,KAAK,EAAE,CAAC;YAC5C,CAAC;QACH,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,SAAS,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;;AAED,6CAA6C;AAC7C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC","sourcesContent":["/**\n * Base API Client - Shared HTTP functionality for all API clients.\n */\n\nimport { QueryClient } from '@tanstack/query-core';\n\nimport {\n API_URLS,\n STALE_TIMES,\n GC_TIMES,\n authQueryKeys,\n calculateRetryDelay,\n shouldRetry,\n HttpError,\n} from './shared-types';\nimport type { ApiPlatformClientOptions } from './shared-types';\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 constructor(options: ApiPlatformClientOptions) {\n this.clientProduct = options.clientProduct;\n this.clientVersion = options.clientVersion ?? '1.0.0';\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-Client-Product': this.clientProduct,\n 'X-Client-Version': this.clientVersion,\n };\n\n // Use TanStack Query to cache the bearer token\n // Wrap getBearerToken to return null instead of undefined (TanStack Query doesn't allow undefined)\n if (this.getBearerToken) {\n const { getBearerToken } = this;\n const token = await this.#queryClientInstance.fetchQuery({\n queryKey: authQueryKeys.bearerToken(),\n queryFn: async () => (await getBearerToken()) ?? null,\n staleTime: STALE_TIMES.AUTH_TOKEN,\n gcTime: GC_TIMES.DEFAULT,\n });\n if (token) {\n headers.Authorization = `Bearer ${token}`;\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 calculateRetryDelay,\n shouldRetry,\n HttpError,\n} from './shared-types';\nimport type { ApiPlatformClientOptions } from './shared-types';\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 ?? '1.0.0';\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-Client-Product': this.clientProduct,\n 'X-Client-Version': 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"]}
@@ -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.authQueryKeys = exports.RETRY_CONFIG = exports.GC_TIMES = exports.STALE_TIMES = exports.API_URLS = void 0;
6
+ exports.HttpError = exports.shouldRetry = exports.calculateRetryDelay = exports.RETRY_CONFIG = exports.GC_TIMES = exports.STALE_TIMES = exports.API_URLS = void 0;
7
7
  // ============================================================================
8
8
  // CONSTANTS
9
9
  // ============================================================================
@@ -41,12 +41,6 @@ exports.RETRY_CONFIG = {
41
41
  MAX_DELAY: 5000,
42
42
  };
43
43
  // ============================================================================
44
- // QUERY KEYS (Auth only - client-specific keys in their respective folders)
45
- // ============================================================================
46
- exports.authQueryKeys = {
47
- bearerToken: () => ['auth', 'bearerToken'],
48
- };
49
- // ============================================================================
50
44
  // HELPER FUNCTIONS
51
45
  // ============================================================================
52
46
  /**
@@ -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 { QueryClient, QueryKey } 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\nexport type FetchOptions = {\n /** Custom stale time (ms) */\n staleTime?: number;\n /** Custom GC time (ms) */\n gcTime?: number;\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// QUERY KEYS (Auth only - client-specific keys in their respective folders)\n// ============================================================================\n\nexport const authQueryKeys = {\n bearerToken: (): QueryKey => ['auth', 'bearerToken'],\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":";AAAA;;GAEG;;;AAmJH,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,oBAAoB;AACP,QAAA,QAAQ,GAAG;IACtB,QAAQ,EAAE,qCAAqC;IAC/C,MAAM,EAAE,kCAAkC;IAC1C,KAAK,EAAE,kCAAkC;IACzC,MAAM,EAAE,mCAAmC;CACnC,CAAC;AAEX,gDAAgD;AACnC,QAAA,WAAW,GAAG;IACzB,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,mCAAmC;IAC9D,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,aAAa;IAChC,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,WAAW;IAChC,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACvC,kBAAkB,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACjD,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IAC3C,UAAU,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACzC,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IAC3C,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IACrC,YAAY,EAAE,EAAE,GAAG,IAAI,EAAE,aAAa;IACtC,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,aAAa;CACzB,CAAC;AAEX,oCAAoC;AACvB,QAAA,QAAQ,GAAG;IACtB,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IACpC,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACvC,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;CAC1B,CAAC;AAEX,0BAA0B;AACb,QAAA,YAAY,GAAG;IAC1B,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,IAAK;CACR,CAAC;AAEX,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;;;;GAKG;AACH,SAAgB,mBAAmB,CAAC,YAAoB;IACtD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,oBAAY,CAAC,UAAU,GAAG,CAAC,IAAI,YAAY,EAC3C,oBAAY,CAAC,SAAS,CACvB,CAAC;IACF,OAAO,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC;AAND,kDAMC;AAED;;;;;;GAMG;AACH,SAAgB,WAAW,CAAC,YAAoB,EAAE,KAAc;IAC9D,+EAA+E;IAC/E,IAAI,YAAY,GAAG,oBAAY,CAAC,WAAW,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,YAAY,KAAK,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;QAChD,MAAM,EAAE,MAAM,EAAE,GAAG,KAA2B,CAAC;QAC/C,4DAA4D;QAC5D,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACtE,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAdD,kCAcC;AAED,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E,MAAa,SAAU,SAAQ,KAAK;IASlC,YACE,OAAe,EACf,MAAc,EACd,UAAkB,EAClB,GAAW,EACX,IAAc;QAEd,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAvBD,8BAuBC","sourcesContent":["/**\n * Shared types, constants, and utilities for the API Platform Client.\n */\n\nimport type { 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\nexport type FetchOptions = {\n /** Custom stale time (ms) */\n staleTime?: number;\n /** Custom GC time (ms) */\n gcTime?: number;\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"]}
@@ -106,9 +106,6 @@ export declare const RETRY_CONFIG: {
106
106
  readonly BASE_DELAY: 1000;
107
107
  readonly MAX_DELAY: 5000;
108
108
  };
109
- export declare const authQueryKeys: {
110
- readonly bearerToken: () => readonly unknown[];
111
- };
112
109
  /**
113
110
  * Calculate retry delay with exponential backoff and jitter.
114
111
  *
@@ -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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"}
@@ -106,9 +106,6 @@ export declare const RETRY_CONFIG: {
106
106
  readonly BASE_DELAY: 1000;
107
107
  readonly MAX_DELAY: 5000;
108
108
  };
109
- export declare const authQueryKeys: {
110
- readonly bearerToken: () => readonly unknown[];
111
- };
112
109
  /**
113
110
  * Calculate retry delay with exponential backoff and jitter.
114
111
  *
@@ -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":"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"}
@@ -38,12 +38,6 @@ export const RETRY_CONFIG = {
38
38
  MAX_DELAY: 5000,
39
39
  };
40
40
  // ============================================================================
41
- // QUERY KEYS (Auth only - client-specific keys in their respective folders)
42
- // ============================================================================
43
- export const authQueryKeys = {
44
- bearerToken: () => ['auth', 'bearerToken'],
45
- };
46
- // ============================================================================
47
41
  // HELPER FUNCTIONS
48
42
  // ============================================================================
49
43
  /**
@@ -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 { QueryClient, QueryKey } 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\nexport type FetchOptions = {\n /** Custom stale time (ms) */\n staleTime?: number;\n /** Custom GC time (ms) */\n gcTime?: number;\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// QUERY KEYS (Auth only - client-specific keys in their respective folders)\n// ============================================================================\n\nexport const authQueryKeys = {\n bearerToken: (): QueryKey => ['auth', 'bearerToken'],\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 { 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\nexport type FetchOptions = {\n /** Custom stale time (ms) */\n staleTime?: number;\n /** Custom GC time (ms) */\n gcTime?: number;\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/core-backend",
3
- "version": "5.0.0-preview-3ec2a74",
3
+ "version": "5.0.0-preview-6ae8a59c",
4
4
  "description": "Core backend services for MetaMask",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -50,7 +50,7 @@
50
50
  "dependencies": {
51
51
  "@metamask/accounts-controller": "^35.0.2",
52
52
  "@metamask/controller-utils": "^11.18.0",
53
- "@metamask/keyring-controller": "^25.0.0",
53
+ "@metamask/keyring-controller": "^25.1.0",
54
54
  "@metamask/messenger": "^0.3.0",
55
55
  "@metamask/profile-sync-controller": "^27.0.0",
56
56
  "@metamask/utils": "^11.9.0",