diff --git a/apps/deploy-web/src/queries/useDeploymentQuery.ts b/apps/deploy-web/src/queries/useDeploymentQuery.ts index b684886881..e3cee4b857 100644 --- a/apps/deploy-web/src/queries/useDeploymentQuery.ts +++ b/apps/deploy-web/src/queries/useDeploymentQuery.ts @@ -1,10 +1,11 @@ +import { getAllItems } from "@akashnetwork/http-sdk"; import type { QueryKey, UseQueryOptions } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query"; import type { AxiosInstance } from "axios"; import { useServices } from "@src/context/ServicesProvider"; import type { DeploymentDto, RpcDeployment } from "@src/types/deployment"; -import { ApiUrlService, loadWithPagination } from "@src/utils/apiUtils"; +import { ApiUrlService } from "@src/utils/apiUtils"; import { deploymentToDto } from "@src/utils/deploymentDetailUtils"; import { QueryKeys } from "./queryKeys"; @@ -12,7 +13,12 @@ import { QueryKeys } from "./queryKeys"; async function getDeploymentList(chainApiHttpClient: AxiosInstance, address: string) { if (!address) return []; - const deployments = await loadWithPagination(ApiUrlService.deploymentList("", address), "deployments", 1000, chainApiHttpClient); + const deployments = await getAllItems(async params => { + const response = await chainApiHttpClient.get(ApiUrlService.deploymentList("", address), { + params: { "pagination.limit": 1000, ...params } + }); + return { items: response.data.deployments, pagination: response.data.pagination }; + }); return deployments.map(d => deploymentToDto(d)); } diff --git a/apps/deploy-web/src/queries/useGrantsQuery.spec.tsx b/apps/deploy-web/src/queries/useGrantsQuery.spec.tsx index 321e4b0298..9855ea20c5 100644 --- a/apps/deploy-web/src/queries/useGrantsQuery.spec.tsx +++ b/apps/deploy-web/src/queries/useGrantsQuery.spec.tsx @@ -190,7 +190,8 @@ describe("useGrantsQuery", () => { await vi.waitFor(() => { expect(chainApiHttpClient.get).toHaveBeenCalledWith( - expect.stringContaining("/cosmos/feegrant/v1beta1/allowances/test-address?pagination.limit=1000&pagination.count_total=true") + expect.stringContaining("/cosmos/feegrant/v1beta1/allowances/test-address"), + expect.objectContaining({ params: expect.objectContaining({ "pagination.limit": 1000, "pagination.count_total": "true" }) }) ); expect(result.current.isSuccess).toBe(true); expect(result.current.data).toEqual(mockData); diff --git a/apps/deploy-web/src/queries/useGrantsQuery.ts b/apps/deploy-web/src/queries/useGrantsQuery.ts index cf08858e0b..5d0ee3db09 100644 --- a/apps/deploy-web/src/queries/useGrantsQuery.ts +++ b/apps/deploy-web/src/queries/useGrantsQuery.ts @@ -1,11 +1,12 @@ import type { DepositDeploymentGrant } from "@akashnetwork/http-sdk"; +import { getAllItems } from "@akashnetwork/http-sdk"; import type { UseQueryOptions } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query"; import type { AxiosInstance } from "axios"; import { useServices } from "@src/context/ServicesProvider"; import type { AllowanceType, PaginatedAllowanceType, PaginatedGrantType } from "@src/types/grant"; -import { ApiUrlService, loadWithPagination } from "@src/utils/apiUtils"; +import { ApiUrlService } from "@src/utils/apiUtils"; import { QueryKeys } from "./queryKeys"; export function useGranterGrants( @@ -54,7 +55,12 @@ export function useAllowancesIssued( } async function getAllowancesGranted(chainApiHttpClient: AxiosInstance, address: string) { - return await loadWithPagination(ApiUrlService.allowancesGranted("", address), "allowances", 1000, chainApiHttpClient); + return getAllItems(async params => { + const response = await chainApiHttpClient.get(ApiUrlService.allowancesGranted("", address), { + params: { "pagination.limit": 1000, ...params } + }); + return { items: response.data.allowances, pagination: response.data.pagination }; + }); } export function useAllowancesGranted(address: string, options: Omit, "queryKey" | "queryFn"> = {}) { diff --git a/apps/deploy-web/src/queries/useLeaseQuery.spec.tsx b/apps/deploy-web/src/queries/useLeaseQuery.spec.tsx index f7cf4402f7..b9fcba4d10 100644 --- a/apps/deploy-web/src/queries/useLeaseQuery.spec.tsx +++ b/apps/deploy-web/src/queries/useLeaseQuery.spec.tsx @@ -153,7 +153,7 @@ describe("useLeaseQuery", () => { expect(result.current.isSuccess).toBe(true); }); - expect(chainApiHttpClient.get).toHaveBeenCalledWith(expect.stringContaining(`filters.dseq=${mockDeployment.dseq}`)); + expect(chainApiHttpClient.get).toHaveBeenCalledWith(expect.stringContaining(`filters.dseq=${mockDeployment.dseq}`), expect.anything()); expect(result.current.data).toEqual([leaseToDto(mockLeases[0], mockDeployment)]); }); @@ -228,7 +228,7 @@ describe("useLeaseQuery", () => { await vi.waitFor(() => { expect(result.current.isSuccess).toBe(true); }); - expect(chainApiHttpClient.get).toHaveBeenCalledWith(expect.stringContaining("filters.owner=test-address")); + expect(chainApiHttpClient.get).toHaveBeenCalledWith(expect.stringContaining("filters.owner=test-address"), expect.anything()); expect(result.current.data).toEqual([leaseToDto(mockLeases[0], undefined as any)]); }); diff --git a/apps/deploy-web/src/queries/useLeaseQuery.ts b/apps/deploy-web/src/queries/useLeaseQuery.ts index 573216fcd1..65be3ecd81 100644 --- a/apps/deploy-web/src/queries/useLeaseQuery.ts +++ b/apps/deploy-web/src/queries/useLeaseQuery.ts @@ -1,4 +1,4 @@ -import { isHttpError } from "@akashnetwork/http-sdk"; +import { getAllItems, isHttpError } from "@akashnetwork/http-sdk"; import type { UseQueryOptions } from "@tanstack/react-query"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import type { AxiosInstance } from "axios"; @@ -8,7 +8,7 @@ import { useProviderCredentials } from "@src/hooks/useProviderCredentials/usePro import { useScopedFetchProviderUrl } from "@src/hooks/useScopedFetchProviderUrl"; import type { DeploymentDto, LeaseDto, RpcLease } from "@src/types/deployment"; import type { ApiProviderList } from "@src/types/provider"; -import { ApiUrlService, loadWithPagination } from "@src/utils/apiUtils"; +import { ApiUrlService } from "@src/utils/apiUtils"; import { leaseToDto } from "@src/utils/deploymentDetailUtils"; import { QueryKeys } from "./queryKeys"; @@ -18,10 +18,14 @@ async function getDeploymentLeases(chainApiHttpClient: AxiosInstance, address: s return null; } - const response = await loadWithPagination(ApiUrlService.leaseList("", address, deployment?.dseq), "leases", 1000, chainApiHttpClient); - const leases = response.map(l => leaseToDto(l, deployment)); + const leases = await getAllItems(async params => { + const response = await chainApiHttpClient.get(ApiUrlService.leaseList("", address, deployment?.dseq), { + params: { "pagination.limit": 1000, ...params } + }); + return { items: response.data.leases, pagination: response.data.pagination }; + }); - return leases; + return leases.map(l => leaseToDto(l, deployment)); } export function useDeploymentLeaseList( @@ -53,10 +57,14 @@ async function getAllLeases(chainApiHttpClient: AxiosInstance, address: string, return null; } - const response = await loadWithPagination(ApiUrlService.leaseList("", address, deployment?.dseq), "leases", 1000, chainApiHttpClient); - const leases = response.map(l => leaseToDto(l, deployment)); + const leases = await getAllItems(async params => { + const response = await chainApiHttpClient.get(ApiUrlService.leaseList("", address, deployment?.dseq), { + params: { "pagination.limit": 1000, ...params } + }); + return { items: response.data.leases, pagination: response.data.pagination }; + }); - return leases; + return leases.map(l => leaseToDto(l, deployment)); } export function useAllLeases(address: string, options = {}) { diff --git a/apps/deploy-web/src/services/wallet-balances/wallet-balances.service.ts b/apps/deploy-web/src/services/wallet-balances/wallet-balances.service.ts index b0667a99b5..b68255d690 100644 --- a/apps/deploy-web/src/services/wallet-balances/wallet-balances.service.ts +++ b/apps/deploy-web/src/services/wallet-balances/wallet-balances.service.ts @@ -1,10 +1,11 @@ import type { AuthzHttpService } from "@akashnetwork/http-sdk"; +import { getAllItems } from "@akashnetwork/http-sdk"; import type { AxiosInstance } from "axios"; import type { RestApiBalancesResponseType } from "@src/types"; import type { Balances } from "@src/types/address"; import type { RpcDeployment } from "@src/types/deployment"; -import { ApiUrlService, loadWithPagination } from "@src/utils/apiUtils"; +import { ApiUrlService } from "@src/utils/apiUtils"; import { deploymentToDto } from "@src/utils/deploymentDetailUtils"; export class WalletBalancesService { @@ -22,7 +23,12 @@ export class WalletBalancesService { const [balanceResponse, deploymentGrants, activeDeploymentsResponse] = await Promise.all([ this.chainApiHttpClient.get(ApiUrlService.balance("", address)), this.authzHttpService.getAllDepositDeploymentGrants({ grantee: address, limit: 1000 }), - loadWithPagination(ApiUrlService.deploymentList("", address, true), "deployments", 1000, this.chainApiHttpClient) + getAllItems(async params => { + const response = await this.chainApiHttpClient.get(ApiUrlService.deploymentList("", address, true), { + params: { "pagination.limit": 1000, ...params } + }); + return { items: response.data.deployments, pagination: response.data.pagination }; + }) ]); const deploymentGrantsPerDenom = deploymentGrants.reduce>((acc, grant) => { diff --git a/apps/deploy-web/src/utils/apiUtils.ts b/apps/deploy-web/src/utils/apiUtils.ts index 7715b528f2..dd74ec7a96 100644 --- a/apps/deploy-web/src/utils/apiUtils.ts +++ b/apps/deploy-web/src/utils/apiUtils.ts @@ -1,5 +1,3 @@ -import type { AxiosInstance } from "axios"; - import { services } from "@src/services/app-di-container/browser-di-container"; import networkStore from "@src/store/networkStore"; import { appendSearchParams } from "./urlUtils"; @@ -133,42 +131,3 @@ export class ApiUrlService { return services.apiUrlService.getBaseApiUrlFor(networkStore.selectedNetworkId); } } - -/** - * @deprecated use getAllItems utility from @akashnetwork/http-sdk - * TODO: implement proper pagination on clients - * Issue: https://github.com/akash-network/console/milestone/7 - */ -export async function loadWithPagination(baseUrl: string, dataKey: string, limit: number, httpClient: AxiosInstance) { - let items: T[] = []; - let nextKey: string | null = null; - // let callCount = 1; - // let totalCount = null; - - do { - const _hasQueryParam = hasQueryParam(baseUrl); - let queryUrl = `${baseUrl}${_hasQueryParam ? "&" : "?"}pagination.limit=${limit}&pagination.count_total=true`; - if (nextKey) { - queryUrl += "&pagination.key=" + encodeURIComponent(nextKey); - } - // console.log(`Querying ${dataKey} [${callCount}] from : ${queryUrl}`); - const response = await httpClient.get(queryUrl); - const data = response.data; - - // if (!nextKey) { - // totalCount = data.pagination.total; - // } - - items = items.concat(data[dataKey]); - nextKey = data.pagination.next_key; - // callCount++; - - // console.log(`Got ${items.length} of ${totalCount}`); - } while (nextKey); - - return items.filter(item => item) as T; -} - -function hasQueryParam(url: string) { - return /[?&]/gm.test(url); -} diff --git a/packages/http-sdk/src/deployment/deployment-http.service.ts b/packages/http-sdk/src/deployment/deployment-http.service.ts index b975bc92b5..695370be60 100644 --- a/packages/http-sdk/src/deployment/deployment-http.service.ts +++ b/packages/http-sdk/src/deployment/deployment-http.service.ts @@ -2,7 +2,7 @@ import z from "zod"; import { extractData } from "../http/http.service"; import type { HttpClient } from "../utils/httpClient"; -import { loadWithPagination } from "../utils/pagination.utils"; +import { getAllItems } from "../utils/pagination.utils"; const AttributeSchema = z.object({ key: z.string(), @@ -167,7 +167,14 @@ export class DeploymentHttpService { const defaultLimit = 1000; if (!pagination) { - const allDeployments = await loadWithPagination(baseUrl, "deployments", defaultLimit, this.httpClient); + const allDeployments = await getAllItems(async params => { + const response = extractData( + await this.httpClient.get(baseUrl, { + params: { "pagination.limit": defaultLimit, ...params } + }) + ); + return { items: response.deployments, pagination: response.pagination }; + }); return { deployments: allDeployments, pagination: { diff --git a/packages/http-sdk/src/utils/pagination.utils.ts b/packages/http-sdk/src/utils/pagination.utils.ts index 3e6ab57081..83f39eb8eb 100644 --- a/packages/http-sdk/src/utils/pagination.utils.ts +++ b/packages/http-sdk/src/utils/pagination.utils.ts @@ -2,44 +2,6 @@ import type { LoggerService } from "@akashnetwork/logging"; import { sdkLogger } from "./logger"; -/** - * Helper function to load data with pagination - * @param baseUrl Base URL for the API request - * @param dataKey Key in the response that contains the data array - * @param limit Number of items per page - * @param httpClient HTTP client to use for requests - * @returns Array of items from all pages - */ -export async function loadWithPagination(baseUrl: string, dataKey: string, limit: number, httpClient: { get: (url: string) => Promise }): Promise { - let items: T[] = []; - let nextKey: string | null = null; - - do { - const hasQueryParam = /[?&]/gm.test(baseUrl); - let queryUrl = `${baseUrl}${hasQueryParam ? "&" : "?"}pagination.limit=${limit}&pagination.count_total=true`; - if (nextKey) { - queryUrl += "&pagination.key=" + encodeURIComponent(nextKey); - } - - const response = await httpClient.get(queryUrl); - const data = response.data; - - items = items.concat(data[dataKey]); - nextKey = data.pagination.next_key; - } while (nextKey); - - return items.filter(item => item) as T[]; -} - -/** - * Helper function to check if a URL has query parameters - * @param url URL to check - * @returns Boolean indicating if the URL has query parameters - */ -export function hasQueryParam(url: string): boolean { - return new URL(url).searchParams.size > 0; -} - export async function getAllItems( getItems: (params: Record) => Promise<{ items: T[]; pagination: { next_key: string | null } }>, logger: Pick = sdkLogger