diff --git a/.changeset/eighty-candles-boil.md b/.changeset/eighty-candles-boil.md
new file mode 100644
index 000000000000..2176f1e0d0b7
--- /dev/null
+++ b/.changeset/eighty-candles-boil.md
@@ -0,0 +1,5 @@
+---
+"live-mobile": patch
+---
+
+fix: missing query params for web3hub manifests requests
diff --git a/apps/ledger-live-mobile/android/app/build.gradle b/apps/ledger-live-mobile/android/app/build.gradle
index f4f8b6f848b8..fe8f83e41585 100644
--- a/apps/ledger-live-mobile/android/app/build.gradle
+++ b/apps/ledger-live-mobile/android/app/build.gradle
@@ -128,7 +128,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 36176158
- versionName "3.40.1"
+ versionName "3.48.0"
resValue "string", "build_config_package", "com.ledger.live"
testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
diff --git a/apps/ledger-live-mobile/ios/ledgerlivemobile/Info.plist b/apps/ledger-live-mobile/ios/ledgerlivemobile/Info.plist
index 84466cb13e61..b397005bbb3c 100644
--- a/apps/ledger-live-mobile/ios/ledgerlivemobile/Info.plist
+++ b/apps/ledger-live-mobile/ios/ledgerlivemobile/Info.plist
@@ -35,7 +35,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 3.40.1
+ 3.48.0
CFBundleSignature
????
CFBundleURLTypes
diff --git a/apps/ledger-live-mobile/src/newArch/features/Web3Hub/components/ManifestsList/useManifestsListViewModel.ts b/apps/ledger-live-mobile/src/newArch/features/Web3Hub/components/ManifestsList/useManifestsListViewModel.ts
index 80e306507ddb..d54690e256f2 100644
--- a/apps/ledger-live-mobile/src/newArch/features/Web3Hub/components/ManifestsList/useManifestsListViewModel.ts
+++ b/apps/ledger-live-mobile/src/newArch/features/Web3Hub/components/ManifestsList/useManifestsListViewModel.ts
@@ -1,20 +1,39 @@
import { useInfiniteQuery } from "@tanstack/react-query";
+import useEnv from "@ledgerhq/live-common/hooks/useEnv";
import {
fetchManifests,
selectManifests,
getNextPageParam,
fetchManifestsMock,
} from "LLM/features/Web3Hub/utils/api/manifests";
+import { useLocale } from "~/context/Locale";
-export const queryKey = (selectedCategory: string) => ["web3hub/manifests", selectedCategory];
+export const queryKey = (
+ selectedCategory: string,
+ isExperimentalAppEnabled: boolean,
+ isDebugAppEnabled: boolean,
+ locale: string,
+) => [
+ "web3hub/manifests",
+ selectedCategory,
+ isExperimentalAppEnabled ? "exp-on" : "exp-off",
+ isDebugAppEnabled ? "debug-on" : "debug-off",
+ locale,
+];
const isInTest = process.env.NODE_ENV === "test" || !!process.env.MOCK_WEB3HUB;
const queryFn = isInTest ? fetchManifestsMock : fetchManifests;
export default function useManifestListViewModel(selectedCategory: string) {
+ const isExperimentalAppEnabled = useEnv<"PLATFORM_EXPERIMENTAL_APPS">(
+ "PLATFORM_EXPERIMENTAL_APPS",
+ ) as boolean;
+ const isDebugAppEnabled = useEnv<"PLATFORM_DEBUG">("PLATFORM_DEBUG") as boolean;
+ const { locale } = useLocale();
+
const manifestsQuery = useInfiniteQuery({
- queryKey: queryKey(selectedCategory),
- queryFn: queryFn(selectedCategory, ""),
+ queryKey: queryKey(selectedCategory, isExperimentalAppEnabled, isDebugAppEnabled, locale),
+ queryFn: queryFn(selectedCategory, "", isExperimentalAppEnabled, isDebugAppEnabled, locale),
initialPageParam: 1,
getNextPageParam,
select: selectManifests,
diff --git a/apps/ledger-live-mobile/src/newArch/features/Web3Hub/screens/Web3HubApp/useWeb3HubAppViewModel.ts b/apps/ledger-live-mobile/src/newArch/features/Web3Hub/screens/Web3HubApp/useWeb3HubAppViewModel.ts
index f28685da5575..ee60227da8f0 100644
--- a/apps/ledger-live-mobile/src/newArch/features/Web3Hub/screens/Web3HubApp/useWeb3HubAppViewModel.ts
+++ b/apps/ledger-live-mobile/src/newArch/features/Web3Hub/screens/Web3HubApp/useWeb3HubAppViewModel.ts
@@ -1,15 +1,22 @@
import { useQuery } from "@tanstack/react-query";
import { fetchManifestById, fetchManifestByIdMock } from "LLM/features/Web3Hub/utils/api/manifests";
+import { useLocale } from "~/context/Locale";
-export const queryKey = (manifestId: string) => ["web3hub/manifest", manifestId];
+export const queryKey = (manifestId: string, locale: string) => [
+ "web3hub/manifest",
+ manifestId,
+ locale,
+];
const isInTest = process.env.NODE_ENV === "test" || !!process.env.MOCK_WEB3HUB;
const queryFn = isInTest ? fetchManifestByIdMock : fetchManifestById;
export default function useWeb3HubAppViewModel(manifestId: string) {
+ const { locale } = useLocale();
+
const manifestQuery = useQuery({
- queryKey: queryKey(manifestId),
- queryFn: queryFn(manifestId),
+ queryKey: queryKey(manifestId, locale),
+ queryFn: queryFn(manifestId, locale),
});
return {
diff --git a/apps/ledger-live-mobile/src/newArch/features/Web3Hub/screens/Web3HubSearch/components/SearchList/useSearchListViewModel.ts b/apps/ledger-live-mobile/src/newArch/features/Web3Hub/screens/Web3HubSearch/components/SearchList/useSearchListViewModel.ts
index 84d0691e9a9c..34392e1a0bd6 100644
--- a/apps/ledger-live-mobile/src/newArch/features/Web3Hub/screens/Web3HubSearch/components/SearchList/useSearchListViewModel.ts
+++ b/apps/ledger-live-mobile/src/newArch/features/Web3Hub/screens/Web3HubSearch/components/SearchList/useSearchListViewModel.ts
@@ -1,20 +1,44 @@
+import { useMemo } from "react";
import { useInfiniteQuery } from "@tanstack/react-query";
+import useEnv from "@ledgerhq/live-common/hooks/useEnv";
import {
fetchManifests,
selectManifests,
getNextPageParam,
fetchManifestsMock,
} from "LLM/features/Web3Hub/utils/api/manifests";
+import { useLocale } from "~/context/Locale";
-export const queryKey = (search: string) => ["web3hub/manifests/search", search];
+export const queryKey = (
+ search: string,
+ isExperimentalAppEnabled: boolean,
+ isDebugAppEnabled: boolean,
+ locale: string,
+) => [
+ "web3hub/manifests/search",
+ search,
+ isExperimentalAppEnabled ? "exp-on" : "exp-off",
+ isDebugAppEnabled ? "debug-on" : "debug-off",
+ locale,
+];
const isInTest = process.env.NODE_ENV === "test" || !!process.env.MOCK_WEB3HUB;
const queryFn = isInTest ? fetchManifestsMock : fetchManifests;
export default function useSearchListViewModel(search: string) {
+ const trimmedSearch = useMemo(() => {
+ return search.trim();
+ }, [search]);
+
+ const isExperimentalAppEnabled = useEnv<"PLATFORM_EXPERIMENTAL_APPS">(
+ "PLATFORM_EXPERIMENTAL_APPS",
+ ) as boolean;
+ const isDebugAppEnabled = useEnv<"PLATFORM_DEBUG">("PLATFORM_DEBUG") as boolean;
+ const { locale } = useLocale();
+
const manifestsQuery = useInfiniteQuery({
- queryKey: queryKey(search),
- queryFn: queryFn("", search),
+ queryKey: queryKey(trimmedSearch, isExperimentalAppEnabled, isDebugAppEnabled, locale),
+ queryFn: queryFn("", trimmedSearch, isExperimentalAppEnabled, isDebugAppEnabled, locale),
initialPageParam: 1,
getNextPageParam,
select: selectManifests,
diff --git a/apps/ledger-live-mobile/src/newArch/features/Web3Hub/utils/api/manifests.ts b/apps/ledger-live-mobile/src/newArch/features/Web3Hub/utils/api/manifests.ts
index dc27055fd26e..5e2a3b39da80 100644
--- a/apps/ledger-live-mobile/src/newArch/features/Web3Hub/utils/api/manifests.ts
+++ b/apps/ledger-live-mobile/src/newArch/features/Web3Hub/utils/api/manifests.ts
@@ -1,3 +1,5 @@
+import { Platform } from "react-native";
+import VersionNumber from "react-native-version-number";
import network from "@ledgerhq/live-network/network";
import { GetNextPageParamFunction, InfiniteData, QueryFunction } from "@tanstack/react-query";
import { LiveAppManifest } from "@ledgerhq/live-common/platform/types";
@@ -31,28 +33,65 @@ export const fetchManifestsMock: (
return list.slice((pageParam - 1) * PAGE_SIZE, pageParam * PAGE_SIZE);
};
-export const fetchManifests: (
+const PLATFORM = Platform.OS === "ios" ? "ios" : "android";
+const LLVersion = VersionNumber.appVersion;
+
+const apiVersions = ["1.0.0", "2.0.0"];
+
+const defaultBranches = ["stable", "soon"];
+
+type FetchManifests = (
category: string,
search: string,
-) => QueryFunction =
- (category, search) =>
- async ({ pageParam }) => {
- const url = new URL(`${URL_ORIGIN}/api/v2/apps`);
- url.searchParams.set("resultsPerPage", `${PAGE_SIZE}`);
- url.searchParams.set("page", `${pageParam}`);
- if (category !== "all") {
- url.searchParams.set("categories", category);
- }
- // TODO: make sure to trim search
- if (search) {
- url.searchParams.set("search", search);
+ allowExperimentalApps: boolean,
+ allowDebugApps: boolean,
+ lang: string,
+) => QueryFunction;
+
+export const fetchManifests: FetchManifests = (
+ category,
+ search,
+ allowExperimentalApps,
+ allowDebugApps,
+ lang,
+) => {
+ const url = new URL(`${URL_ORIGIN}/api/v2/apps`);
+ url.searchParams.set("llVersion", LLVersion);
+ url.searchParams.set("platform", PLATFORM);
+ url.searchParams.set("private", "false");
+ url.searchParams.set("lang", lang ? lang : "en");
+ apiVersions.forEach(apiVersion => {
+ url.searchParams.append("apiVersion", apiVersion);
+ });
+ const branches = [
+ ...defaultBranches,
+ allowExperimentalApps && "experimental",
+ allowDebugApps && "debug",
+ ];
+ branches.forEach(branch => {
+ if (branch) {
+ url.searchParams.append("branches", branch);
}
+ });
+
+ url.searchParams.set("resultsPerPage", `${PAGE_SIZE}`);
+ if (category !== "all") {
+ url.searchParams.set("categories", category);
+ }
+ // TODO: make sure to trim search
+ if (search) {
+ url.searchParams.set("search", search);
+ }
+
+ return async ({ pageParam }) => {
+ url.searchParams.set("page", `${pageParam}`);
const res = await network({
url: url.toString(),
});
return res.data;
};
+};
export const selectManifests = (data: InfiniteData) => {
return data.pages.flat(1);
@@ -78,11 +117,16 @@ export const fetchManifestByIdMock = (manifestId: string) => async () => {
return manifests.find(mock => mock.id === manifestId);
};
-export const fetchManifestById = (manifestId: string) => async () => {
+export const fetchManifestById = (manifestId: string, lang: string) => {
const url = new URL(`${URL_ORIGIN}/api/v2/apps/${manifestId}`);
+ url.searchParams.set("llVersion", LLVersion);
+ url.searchParams.set("platform", PLATFORM);
+ url.searchParams.set("lang", lang ? lang : "en");
- const res = await network({
- url: url.toString(),
- });
- return res.data;
+ return async () => {
+ const res = await network({
+ url: url.toString(),
+ });
+ return res.data;
+ };
};