@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 +2 -2
- package/dist/api/ApiPlatformClient.cjs +6 -2
- package/dist/api/ApiPlatformClient.cjs.map +1 -1
- package/dist/api/ApiPlatformClient.d.cts +3 -0
- package/dist/api/ApiPlatformClient.d.cts.map +1 -1
- package/dist/api/ApiPlatformClient.d.mts +3 -0
- package/dist/api/ApiPlatformClient.d.mts.map +1 -1
- package/dist/api/ApiPlatformClient.mjs +6 -2
- package/dist/api/ApiPlatformClient.mjs.map +1 -1
- package/dist/api/base-client.cjs +38 -10
- package/dist/api/base-client.cjs.map +1 -1
- package/dist/api/base-client.d.cts +11 -0
- package/dist/api/base-client.d.cts.map +1 -1
- package/dist/api/base-client.d.mts +11 -0
- package/dist/api/base-client.d.mts.map +1 -1
- package/dist/api/base-client.mjs +38 -10
- package/dist/api/base-client.mjs.map +1 -1
- package/dist/api/shared-types.cjs +1 -7
- package/dist/api/shared-types.cjs.map +1 -1
- package/dist/api/shared-types.d.cts +0 -3
- package/dist/api/shared-types.d.cts.map +1 -1
- package/dist/api/shared-types.d.mts +0 -3
- package/dist/api/shared-types.d.mts.map +1 -1
- package/dist/api/shared-types.mjs +0 -6
- package/dist/api/shared-types.mjs.map +1 -1
- package/package.json +2 -2
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.
|
|
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").
|
|
157
|
-
queryKey:
|
|
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,
|
|
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;
|
|
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;
|
|
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,
|
|
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").
|
|
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,
|
|
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"]}
|
package/dist/api/base-client.cjs
CHANGED
|
@@ -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
|
-
//
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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":";AAAA;;GAEG;;;;;;;;;;;;;;;AAEH,qDAAmD;
|
|
1
|
+
{"version":3,"file":"base-client.cjs","sourceRoot":"","sources":["../../src/api/base-client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Base API Client - Shared HTTP functionality for all API clients.\n */\n\nimport { QueryClient } from '@tanstack/query-core';\nimport type { QueryKey } from '@tanstack/query-core';\n\nimport {\n API_URLS,\n STALE_TIMES,\n GC_TIMES,\n calculateRetryDelay,\n shouldRetry,\n HttpError,\n} from './shared-types';\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;
|
|
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;
|
|
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"}
|
package/dist/api/base-client.mjs
CHANGED
|
@@ -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,
|
|
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
|
-
//
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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;
|
|
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.
|
|
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":";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,
|
|
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 } 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":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,
|
|
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":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"shared-types.d.mts","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,6BAA6B;AAMxD;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAEzB,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,MAAM,GACN,KAAK,GACL,KAAK,GAEL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,CAAC;AAEV;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iCAAiC;IACjC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iCAAiC;IACjC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kCAAkC;IAClC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kCAAkC;IAClC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,mCAAmC;IACnC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iCAAiC;IACjC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,wBAAwB,EAAE,MAAM,CAAC;IACjC,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yBAAyB;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAMF,MAAM,MAAM,wBAAwB,GAAG;IACrC,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACnD,2CAA2C;IAC3C,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAMF,oBAAoB;AACpB,eAAO,MAAM,QAAQ;;;;;CAKX,CAAC;AAEX,gDAAgD;AAChD,eAAO,MAAM,WAAW;;;;;;;;;;;;CAYd,CAAC;AAEX,oCAAoC;AACpC,eAAO,MAAM,QAAQ;;;;CAIX,CAAC;AAEX,0BAA0B;AAC1B,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAMX;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAczE;AAMD,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;gBAGrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,OAAO;CASjB"}
|
|
@@ -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":"AAAA;;GAEG;AAmJH,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,oBAAoB;AACpB,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,QAAQ,EAAE,qCAAqC;IAC/C,MAAM,EAAE,kCAAkC;IAC1C,KAAK,EAAE,kCAAkC;IACzC,MAAM,EAAE,mCAAmC;CACnC,CAAC;AAEX,gDAAgD;AAChD,MAAM,CAAC,MAAM,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;AACpC,MAAM,CAAC,MAAM,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;AAC1B,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,IAAK;CACR,CAAC;AAEX,+EAA+E;AAC/E,
|
|
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-
|
|
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.
|
|
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",
|