@luxexchange/api 1.0.0 → 1.0.2

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.
Files changed (48) hide show
  1. package/dist/client.d.ts +22 -0
  2. package/dist/client.d.ts.map +1 -0
  3. package/dist/client.js +56 -0
  4. package/dist/hooks/index.d.ts +6 -0
  5. package/dist/hooks/index.d.ts.map +1 -0
  6. package/dist/hooks/index.js +5 -0
  7. package/dist/hooks/use-token-list.d.ts +22 -0
  8. package/dist/hooks/use-token-list.d.ts.map +1 -0
  9. package/dist/hooks/use-token-list.js +27 -0
  10. package/dist/hooks/use-token-price.d.ts +15 -0
  11. package/dist/hooks/use-token-price.d.ts.map +1 -0
  12. package/dist/hooks/use-token-price.js +63 -0
  13. package/dist/index.d.ts +6 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +5 -0
  16. package/package.json +10 -11
  17. package/project.json +1 -7
  18. package/src/clients/base/errors.test.ts +39 -0
  19. package/src/clients/base/errors.ts +9 -1
  20. package/src/clients/base/urls.test.ts +6 -6
  21. package/src/clients/base/urls.ts +3 -3
  22. package/src/clients/compliance/createComplianceApiClient.ts +40 -0
  23. package/src/clients/compliance/types.ts +15 -0
  24. package/src/clients/dataApi/createDataApiServiceClient.ts +4 -4
  25. package/src/clients/dataApi/getGetPortfolioQueryOptions.test.ts +1 -1
  26. package/src/clients/dataApi/getGetPortfolioQueryOptions.ts +6 -2
  27. package/src/clients/embeddedWallet/createEmbeddedWalletApiClient.ts +254 -82
  28. package/src/clients/gasService/createGasServiceClient.ts +21 -0
  29. package/src/clients/graphql/queries.graphql +0 -183
  30. package/src/clients/graphql/queries.ts +0 -2
  31. package/src/clients/graphql/schema.graphql +603 -594
  32. package/src/clients/graphql/web/activity.graphql +0 -6
  33. package/src/clients/graphql/web/landing.graphql +0 -20
  34. package/src/clients/graphql/web/token.graphql +21 -3
  35. package/src/clients/lux/createLuxApiClient.ts +1 -18
  36. package/src/clients/trading/api.json +1 -1
  37. package/src/clients/trading/createTradingApiClient.ts +2 -2
  38. package/src/clients/unitags/createUnitagsApiClient.test.ts +1 -1
  39. package/src/clients/x/createXVerificationServiceClient.ts +26 -0
  40. package/src/components/ApiInit.test.tsx +1 -1
  41. package/src/getWebSocketUrl.ts +7 -4
  42. package/src/index.ts +36 -9
  43. package/src/session/createWithSessionRetry.ts +1 -1
  44. package/stubs/privy-service-pb.d.ts +150 -3
  45. package/.depcheckrc +0 -17
  46. package/.eslintrc.js +0 -30
  47. package/src/clients/graphql/web/nft/CollectionSearch.graphql +0 -34
  48. package/src/clients/graphql/web/portfolios.graphql +0 -68
@@ -0,0 +1,22 @@
1
+ import { QueryClient } from '@tanstack/react-query';
2
+ /**
3
+ * Create a React Query client with Lux Exchange defaults
4
+ */
5
+ export declare function createQueryClient(): QueryClient;
6
+ /**
7
+ * API base URLs
8
+ */
9
+ export declare const API_URLS: {
10
+ readonly TOKEN_LIST: "https://tokens.lux.network";
11
+ readonly PRICE_API: "https://api.lux.network/prices";
12
+ readonly ANALYTICS_API: "https://api.lux.network/analytics";
13
+ readonly V2_SUBGRAPH: "https://api.lux.network/subgraphs/exchange-v2";
14
+ readonly V3_SUBGRAPH: "https://api.lux.network/subgraphs/exchange-v3";
15
+ };
16
+ /**
17
+ * Fetch with timeout
18
+ */
19
+ export declare function fetchWithTimeout(url: string, options?: RequestInit & {
20
+ timeout?: number;
21
+ }): Promise<Response>;
22
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD;;GAEG;AACH,wBAAgB,iBAAiB,gBAmBhC;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ;;;;;;CAaX,CAAA;AAEV;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,WAAW,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/C,OAAO,CAAC,QAAQ,CAAC,CAenB"}
package/dist/client.js ADDED
@@ -0,0 +1,56 @@
1
+ import { QueryClient } from '@tanstack/react-query';
2
+ /**
3
+ * Create a React Query client with Lux Exchange defaults
4
+ */
5
+ export function createQueryClient() {
6
+ return new QueryClient({
7
+ defaultOptions: {
8
+ queries: {
9
+ // 30 seconds stale time by default
10
+ staleTime: 30_000,
11
+ // 5 minutes cache time
12
+ gcTime: 5 * 60 * 1000,
13
+ // Retry failed queries once
14
+ retry: 1,
15
+ // Don't refetch on window focus by default
16
+ refetchOnWindowFocus: false,
17
+ },
18
+ mutations: {
19
+ // Retry mutations once
20
+ retry: 1,
21
+ },
22
+ },
23
+ });
24
+ }
25
+ /**
26
+ * API base URLs
27
+ */
28
+ export const API_URLS = {
29
+ // Token list API
30
+ TOKEN_LIST: 'https://tokens.lux.network',
31
+ // Price API
32
+ PRICE_API: 'https://api.lux.network/prices',
33
+ // Analytics API
34
+ ANALYTICS_API: 'https://api.lux.network/analytics',
35
+ // Subgraph endpoints
36
+ V2_SUBGRAPH: 'https://api.lux.network/subgraphs/exchange-v2',
37
+ V3_SUBGRAPH: 'https://api.lux.network/subgraphs/exchange-v3',
38
+ };
39
+ /**
40
+ * Fetch with timeout
41
+ */
42
+ export async function fetchWithTimeout(url, options = {}) {
43
+ const { timeout = 10_000, ...fetchOptions } = options;
44
+ const controller = new AbortController();
45
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
46
+ try {
47
+ const response = await fetch(url, {
48
+ ...fetchOptions,
49
+ signal: controller.signal,
50
+ });
51
+ return response;
52
+ }
53
+ finally {
54
+ clearTimeout(timeoutId);
55
+ }
56
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * API Hooks
3
+ */
4
+ export * from './use-token-list';
5
+ export * from './use-token-price';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * API Hooks
3
+ */
4
+ export * from './use-token-list';
5
+ export * from './use-token-price';
@@ -0,0 +1,22 @@
1
+ export interface TokenListToken {
2
+ address: string;
3
+ chainId: number;
4
+ decimals: number;
5
+ symbol: string;
6
+ name: string;
7
+ logoURI?: string;
8
+ }
9
+ export interface TokenList {
10
+ name: string;
11
+ tokens: TokenListToken[];
12
+ version: {
13
+ major: number;
14
+ minor: number;
15
+ patch: number;
16
+ };
17
+ }
18
+ /**
19
+ * Fetch and cache token list
20
+ */
21
+ export declare function useTokenList(chainId: number): import("@tanstack/react-query").UseQueryResult<TokenListToken[], Error>;
22
+ //# sourceMappingURL=use-token-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-token-list.d.ts","sourceRoot":"","sources":["../../src/hooks/use-token-list.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,2EAwB3C"}
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+ import { useQuery } from '@tanstack/react-query';
3
+ import { fetchWithTimeout, API_URLS } from '../client';
4
+ /**
5
+ * Fetch and cache token list
6
+ */
7
+ export function useTokenList(chainId) {
8
+ return useQuery({
9
+ queryKey: ['tokenList', chainId],
10
+ queryFn: async () => {
11
+ try {
12
+ const response = await fetchWithTimeout(`${API_URLS.TOKEN_LIST}/lux-default.json`);
13
+ if (!response.ok) {
14
+ throw new Error('Failed to fetch token list');
15
+ }
16
+ const data = await response.json();
17
+ // Filter tokens for the specified chain
18
+ return data.tokens.filter((token) => token.chainId === chainId);
19
+ }
20
+ catch (error) {
21
+ console.error('Failed to fetch token list:', error);
22
+ return [];
23
+ }
24
+ },
25
+ staleTime: 5 * 60 * 1000, // 5 minutes
26
+ });
27
+ }
@@ -0,0 +1,15 @@
1
+ import type { Address } from 'viem';
2
+ export interface TokenPrice {
3
+ address: Address;
4
+ priceUSD: number;
5
+ change24h: number;
6
+ }
7
+ /**
8
+ * Fetch token price in USD
9
+ */
10
+ export declare function useTokenPrice(address: Address | undefined, chainId: number): import("@tanstack/react-query").UseQueryResult<TokenPrice | null, Error>;
11
+ /**
12
+ * Fetch multiple token prices
13
+ */
14
+ export declare function useTokenPrices(addresses: Address[], chainId: number): import("@tanstack/react-query").UseQueryResult<Map<`0x${string}`, TokenPrice>, Error>;
15
+ //# sourceMappingURL=use-token-price.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-token-price.d.ts","sourceRoot":"","sources":["../../src/hooks/use-token-price.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,4EAyB1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,yFAoCnE"}
@@ -0,0 +1,63 @@
1
+ 'use client';
2
+ import { useQuery } from '@tanstack/react-query';
3
+ import { fetchWithTimeout, API_URLS } from '../client';
4
+ /**
5
+ * Fetch token price in USD
6
+ */
7
+ export function useTokenPrice(address, chainId) {
8
+ return useQuery({
9
+ queryKey: ['tokenPrice', address, chainId],
10
+ queryFn: async () => {
11
+ if (!address)
12
+ return null;
13
+ try {
14
+ const response = await fetchWithTimeout(`${API_URLS.PRICE_API}/${chainId}/${address}`);
15
+ if (!response.ok) {
16
+ return null;
17
+ }
18
+ return response.json();
19
+ }
20
+ catch (error) {
21
+ console.error('Failed to fetch token price:', error);
22
+ return null;
23
+ }
24
+ },
25
+ enabled: !!address,
26
+ staleTime: 30_000, // 30 seconds
27
+ refetchInterval: 60_000, // Refetch every minute
28
+ });
29
+ }
30
+ /**
31
+ * Fetch multiple token prices
32
+ */
33
+ export function useTokenPrices(addresses, chainId) {
34
+ return useQuery({
35
+ queryKey: ['tokenPrices', addresses, chainId],
36
+ queryFn: async () => {
37
+ const priceMap = new Map();
38
+ if (addresses.length === 0)
39
+ return priceMap;
40
+ try {
41
+ const response = await fetchWithTimeout(`${API_URLS.PRICE_API}/${chainId}/batch`, {
42
+ method: 'POST',
43
+ headers: { 'Content-Type': 'application/json' },
44
+ body: JSON.stringify({ addresses }),
45
+ });
46
+ if (!response.ok) {
47
+ return priceMap;
48
+ }
49
+ const prices = await response.json();
50
+ prices.forEach((price) => {
51
+ priceMap.set(price.address, price);
52
+ });
53
+ return priceMap;
54
+ }
55
+ catch (error) {
56
+ console.error('Failed to fetch token prices:', error);
57
+ return priceMap;
58
+ }
59
+ },
60
+ enabled: addresses.length > 0,
61
+ staleTime: 30_000,
62
+ });
63
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @luxfi/api - Data fetching and API integration
3
+ */
4
+ export * from './client';
5
+ export * from './hooks';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @luxfi/api - Data fetching and API integration
3
+ */
4
+ export * from './client';
5
+ export * from './hooks';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luxexchange/api",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "scripts": {
5
5
  "lint:biome": "nx lint:biome api",
6
6
  "lint:biome:fix": "nx lint:biome:fix api",
@@ -12,7 +12,6 @@
12
12
  "typecheck:tsgo": "nx typecheck:tsgo api",
13
13
  "prepare": "nx prepare api",
14
14
  "test": "nx test api",
15
- "test:coverage": "nx test:coverage api",
16
15
  "graphql:generate": "nx graphql:generate api",
17
16
  "graphql:schema": "nx graphql:schema api",
18
17
  "tradingapi:schema": "nx tradingapi:schema api",
@@ -29,18 +28,19 @@
29
28
  "@connectrpc/connect-web": "1.5.0",
30
29
  "@ethersproject/providers": "5.7.2",
31
30
  "@tanstack/react-query": "5.90.20",
32
- "@uniswap/client-data-api": "0.0.51",
31
+ "@uniswap/client-data-api": "0.0.59",
33
32
  "@uniswap/client-embeddedwallet": "0.0.16",
34
33
  "@uniswap/client-explore": "0.0.17",
35
34
  "@uniswap/client-for": "0.1.5",
36
- "@uniswap/client-liquidity": "0.0.23",
35
+ "@uniswap/client-liquidity": "0.1.2",
37
36
  "@uniswap/client-notification-service": "0.0.11",
38
- "@luxexchange/config": "^1.0.0",
39
- "@luxexchange/sessions": "^1.0.0",
37
+ "@uniswap/client-unirpc-v2": "0.0.2",
38
+ "@luxexchange/config": "workspace:^",
39
+ "@luxexchange/sessions": "workspace:^",
40
40
  "expo-secure-store": "14.0.1",
41
41
  "graphql": "16.6.0",
42
42
  "react": "19.0.3",
43
- "@luxfi/utilities": "^1.0.0"
43
+ "@luxfi/utilities": "workspace:^"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@graphql-codegen/cli": "3.3.1",
@@ -52,12 +52,11 @@
52
52
  "@types/chrome": "0.0.304",
53
53
  "@types/node": "22.13.1",
54
54
  "@types/react": "19.0.10",
55
- "@typescript/native-preview": "7.0.0-dev.20260108.1",
56
- "@luxfi/eslint-config": "^1.0.0",
55
+ "@typescript/native-preview": "7.0.0-dev.20260311.1",
56
+ "@luxfi/eslint-config": "workspace:^",
57
57
  "@vitest/coverage-v8": "3.2.1",
58
58
  "depcheck": "1.4.7",
59
59
  "eslint": "8.57.1",
60
- "get-graphql-schema": "2.1.2",
61
60
  "openapi-typescript-codegen": "0.27.0",
62
61
  "ts-morph": "23.0.0",
63
62
  "typescript": "5.8.3",
@@ -66,7 +65,7 @@
66
65
  "zod": "4.3.6"
67
66
  },
68
67
  "optionalDependencies": {
69
- "@uniswap/client-privy-embedded-wallet": "0.0.2"
68
+ "@uniswap/client-privy-embedded-wallet": "0.0.5"
70
69
  },
71
70
  "main": "src/index.ts",
72
71
  "private": false,
package/project.json CHANGED
@@ -30,12 +30,6 @@
30
30
  "cwd": "{projectRoot}"
31
31
  }
32
32
  },
33
- "test:coverage": {
34
- "command": "vitest run --coverage",
35
- "options": {
36
- "cwd": "{projectRoot}"
37
- }
38
- },
39
33
  "tradingapi:schema": {
40
34
  "command": "curl https://trading-api-labs.interface.gateway.lux.exchange/v1/api.json -o ./src/clients/trading/api.json",
41
35
  "options": {
@@ -71,7 +65,7 @@
71
65
  "dependsOn": ["tradingapi:generate:openapi"]
72
66
  },
73
67
  "graphql:schema": {
74
- "command": "get-graphql-schema https://api.lux.exchange/v1/graphql -h Origin=https://app.lux.exchange > ./src/clients/graphql/schema.graphql",
68
+ "command": "gh auth status >/dev/null 2>&1 || { echo 'Error: gh CLI is not installed or not authenticated. Run `gh auth login` first.' >&2; exit 1; } && SCHEMA=$(gh api repos/Uniswap/data-api-graphql/contents/graphql/schema.graphql --jq '.content') || { echo 'Error: Failed to fetch schema. Ensure you have access to Uniswap/data-api-graphql.' >&2; exit 1; } && echo '# To update this file, run `bun api graphql:schema`' > ./src/clients/graphql/schema.graphql && echo \"$SCHEMA\" | base64 -d | grep -v '^#' >> ./src/clients/graphql/schema.graphql",
75
69
  "options": {
76
70
  "cwd": "{projectRoot}"
77
71
  }
@@ -0,0 +1,39 @@
1
+ import { Code, ConnectError } from '@connectrpc/connect'
2
+ import { FetchError, is401Error } from '@luxexchange/api/src/clients/base/errors'
3
+ import { describe, expect, it } from 'vitest'
4
+
5
+ describe('is401Error', () => {
6
+ it('returns true for FetchError with 401 status', () => {
7
+ const error = new FetchError({
8
+ response: new Response(null, { status: 401 }),
9
+ })
10
+ expect(is401Error(error)).toBe(true)
11
+ })
12
+
13
+ it('returns false for FetchError with non-401 status', () => {
14
+ const error = new FetchError({
15
+ response: new Response(null, { status: 500 }),
16
+ })
17
+ expect(is401Error(error)).toBe(false)
18
+ })
19
+
20
+ it('returns true for ConnectError with Unauthenticated code', () => {
21
+ const error = new ConnectError('unauthenticated', Code.Unauthenticated)
22
+ expect(is401Error(error)).toBe(true)
23
+ })
24
+
25
+ it('returns false for ConnectError with other codes', () => {
26
+ const error = new ConnectError('not found', Code.NotFound)
27
+ expect(is401Error(error)).toBe(false)
28
+ })
29
+
30
+ it('returns false for generic Error', () => {
31
+ expect(is401Error(new Error('random'))).toBe(false)
32
+ })
33
+
34
+ it('returns false for non-Error values', () => {
35
+ expect(is401Error('string')).toBe(false)
36
+ expect(is401Error(null)).toBe(false)
37
+ expect(is401Error(undefined)).toBe(false)
38
+ })
39
+ })
@@ -1,3 +1,5 @@
1
+ import { Code, ConnectError } from '@connectrpc/connect'
2
+
1
3
  export class FetchError extends Error {
2
4
  response: Response
3
5
  // biome-ignore lint/suspicious/noExplicitAny: Error data can be any shape from API responses
@@ -24,7 +26,13 @@ export function isRateLimitFetchError(error: unknown): boolean {
24
26
  }
25
27
 
26
28
  export function is401Error(error: unknown): boolean {
27
- return error instanceof FetchError && error.response.status === 401
29
+ if (error instanceof FetchError && error.response.status === 401) {
30
+ return true
31
+ }
32
+ if (error instanceof ConnectError && error.code === Code.Unauthenticated) {
33
+ return true
34
+ }
35
+ return false
28
36
  }
29
37
 
30
38
  export function is404Error(error: unknown): boolean {
@@ -4,8 +4,8 @@ import { TrafficFlows } from '@luxexchange/api/src/clients/base/urls'
4
4
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
5
5
 
6
6
  // Mock the platform and environment utilities
7
- vi.mock('@luxfi/utilities/src/environment/env')
8
- vi.mock('@luxfi/utilities/src/platform')
7
+ vi.mock('utilities/src/environment/env')
8
+ vi.mock('utilities/src/platform')
9
9
 
10
10
  const envConfigs = {
11
11
  webProd: {
@@ -229,7 +229,7 @@ describe('urls', () => {
229
229
  )
230
230
 
231
231
  it('generates correct URL for GraphQL flow in web/Playwright', async () => {
232
- vi.doMock('@luxfi/utilities/src/environment/env', () => ({
232
+ vi.doMock('utilities/src/environment/env', () => ({
233
233
  isBetaEnv: () => false,
234
234
  isDevEnv: () => false,
235
235
  isRNDev: () => false,
@@ -237,7 +237,7 @@ describe('urls', () => {
237
237
  isTestEnv: () => false,
238
238
  }))
239
239
 
240
- vi.doMock('@luxfi/utilities/src/platform', () => ({
240
+ vi.doMock('utilities/src/platform', () => ({
241
241
  isAndroid: false,
242
242
  isExtensionApp: false,
243
243
  isMobileApp: false,
@@ -280,7 +280,7 @@ function mockEnvironmentAndPlatform(
280
280
  isWebApp = false,
281
281
  } = overrides
282
282
 
283
- vi.doMock('@luxfi/utilities/src/environment/env', () => ({
283
+ vi.doMock('utilities/src/environment/env', () => ({
284
284
  isBetaEnv: () => isBetaEnv,
285
285
  isDevEnv: () => isDevEnv,
286
286
  isRNDev: () => isRNDev,
@@ -288,7 +288,7 @@ function mockEnvironmentAndPlatform(
288
288
  isTestEnv: () => isTestEnv,
289
289
  }))
290
290
 
291
- vi.doMock('@luxfi/utilities/src/platform', () => ({
291
+ vi.doMock('utilities/src/platform', () => ({
292
292
  isAndroid,
293
293
  isExtensionApp,
294
294
  isMobileApp,
@@ -80,6 +80,6 @@ export const STAGING_ENTRY_GATEWAY_API_BASE_URL: string = 'https://entry-gateway
80
80
  export const PROD_ENTRY_GATEWAY_API_BASE_URL: string = 'https://entry-gateway.backend-prod.api.lux.org'
81
81
 
82
82
  // WebSocket URLs
83
- export const DEV_WEBSOCKET_BASE_URL: string = 'wss://websockets.backend-prod.api.lux.org'
84
- export const STAGING_WEBSOCKET_BASE_URL: string = 'wss://websockets.backend-prod.api.lux.org'
85
- export const PROD_WEBSOCKET_BASE_URL: string = 'wss://websockets.backend-prod.api.lux.org'
83
+ export const DEV_WEBSOCKET_BASE_URL: string = 'wss://websockets.backend-staging.api.uniswap.org'
84
+ export const STAGING_WEBSOCKET_BASE_URL: string = 'wss://websockets.backend-staging.api.uniswap.org'
85
+ export const PROD_WEBSOCKET_BASE_URL: string = 'wss://websockets.backend-prod.api.uniswap.org'
@@ -0,0 +1,40 @@
1
+ import type {
2
+ ComplianceApiClient,
3
+ ComplianceApiClientContext,
4
+ ScreenRequest,
5
+ ScreenResponse,
6
+ } from '@luxexchange/api/src/clients/compliance/types'
7
+
8
+ export type {
9
+ ComplianceApiClient,
10
+ ComplianceApiClientContext,
11
+ ScreenRequest,
12
+ ScreenResponse,
13
+ } from '@luxexchange/api/src/clients/compliance/types'
14
+
15
+ const COMPLIANCE_API_PATHS = {
16
+ screenAddress: '/uniswap.compliancev2service.v1.compliancev2Service/ScreenAddress',
17
+ }
18
+
19
+ export function createComplianceApiClient(ctx: ComplianceApiClientContext): ComplianceApiClient {
20
+ const { baseUrl } = ctx
21
+
22
+ const screenAddress = async (params: ScreenRequest): Promise<ScreenResponse> => {
23
+ const response = await fetch(`${baseUrl}${COMPLIANCE_API_PATHS.screenAddress}`, {
24
+ method: 'POST',
25
+ headers: {
26
+ 'Content-Type': 'application/json',
27
+ },
28
+ body: JSON.stringify(params),
29
+ })
30
+ if (!response.ok) {
31
+ const errorText = await response.text()
32
+ throw new Error(`Compliance screen request failed: ${response.status} ${errorText}`)
33
+ }
34
+ return response.json() as Promise<ScreenResponse>
35
+ }
36
+
37
+ return {
38
+ screenAddress,
39
+ }
40
+ }
@@ -0,0 +1,15 @@
1
+ export interface ScreenRequest {
2
+ address: string
3
+ }
4
+
5
+ export interface ScreenResponse {
6
+ block: boolean
7
+ }
8
+
9
+ export interface ComplianceApiClient {
10
+ screenAddress: (params: ScreenRequest) => Promise<ScreenResponse>
11
+ }
12
+
13
+ export interface ComplianceApiClientContext {
14
+ baseUrl: string
15
+ }
@@ -4,10 +4,10 @@ import { type DataApiService } from '@uniswap/client-data-api/dist/data/v1/api_c
4
4
  import type {
5
5
  GetPortfolioRequest,
6
6
  GetPortfolioResponse,
7
+ ListTokensRequest,
8
+ ListTokensResponse,
7
9
  ListTopPoolsRequest,
8
10
  ListTopPoolsResponse,
9
- ListTopTokensRequest,
10
- ListTopTokensResponse,
11
11
  } from '@uniswap/client-data-api/dist/data/v1/api_pb'
12
12
 
13
13
  export interface DataApiServiceClientContext {
@@ -16,14 +16,14 @@ export interface DataApiServiceClientContext {
16
16
 
17
17
  export interface DataApiServiceClient {
18
18
  getPortfolio: (params: PartialMessage<GetPortfolioRequest>) => Promise<GetPortfolioResponse>
19
- listTopTokens: (params: PartialMessage<ListTopTokensRequest>) => Promise<ListTopTokensResponse>
19
+ listTokens: (params: PartialMessage<ListTokensRequest>) => Promise<ListTokensResponse>
20
20
  listTopPools: (params: PartialMessage<ListTopPoolsRequest>) => Promise<ListTopPoolsResponse>
21
21
  }
22
22
 
23
23
  export function createDataApiServiceClient({ rpcClient }: DataApiServiceClientContext): DataApiServiceClient {
24
24
  return {
25
25
  getPortfolio: (params): Promise<GetPortfolioResponse> => rpcClient.getPortfolio(params),
26
- listTopTokens: (params): Promise<ListTopTokensResponse> => rpcClient.listTopTokens(params),
26
+ listTokens: (params): Promise<ListTokensResponse> => rpcClient.listTokens(params),
27
27
  listTopPools: (params): Promise<ListTopPoolsResponse> => rpcClient.listTopPools(params),
28
28
  }
29
29
  }
@@ -12,7 +12,7 @@ describe('getGetPortfolioQueryOptions', () => {
12
12
  beforeEach(() => {
13
13
  mockClient = {
14
14
  getPortfolio: vi.fn().mockResolvedValue(createMockResponse()),
15
- listTopTokens: vi.fn(),
15
+ listTokens: vi.fn(),
16
16
  listTopPools: vi.fn(),
17
17
  }
18
18
  })
@@ -51,9 +51,13 @@ export function getGetPortfolioQueryOptions(
51
51
  ): QueryOptionsResult<GetPortfolioResponse | undefined, Error, GetPortfolioResponse | undefined, GetPortfolioQueryKey> {
52
52
  const transformedInput = transformInput(input)
53
53
 
54
- const { modifier: _modifier, walletAccount: _walletAccount, ...queryCacheInputs } = transformedInput ?? {}
54
+ const { modifier, walletAccount: _walletAccount, ...queryCacheInputs } = transformedInput ?? {}
55
55
 
56
- const queryCacheInputsSorted = sortQueryCacheInputs(queryCacheInputs)
56
+ const queryCacheInputsSorted = sortQueryCacheInputs({
57
+ ...queryCacheInputs,
58
+ includeSmallBalances: modifier?.includeSmallBalances,
59
+ includeSpamTokens: modifier?.includeSpamTokens,
60
+ })
57
61
 
58
62
  const addressKey = {
59
63
  ...(input?.evmAddress && { evmAddress: input.evmAddress }),