Skip to content

refactor: adjusts authz and provider services to work when blockchain is down#1977

Merged
stalniy merged 3 commits intomainfrom
refactor/chain-api-clients
Sep 30, 2025
Merged

refactor: adjusts authz and provider services to work when blockchain is down#1977
stalniy merged 3 commits intomainfrom
refactor/chain-api-clients

Conversation

@stalniy
Copy link
Contributor

@stalniy stalniy commented Sep 29, 2025

Why

to ensure that blockchain related services will fallback to indexerHttpClient and eventually fail with 404. ref #1950

Summary by CodeRabbit

  • New Features

    • Queries now wait for the authorization service's isReady flag before running, reducing errors and unnecessary calls.
  • Bug Fixes

    • Provider discovery for sending manifests and checking lease status now uses direct database lookup by provider address.
  • Refactor

    • Authorization client unified to use a shared HTTP client; service construction simplified and dependency wiring adjusted.
  • Tests

    • Grants query tests updated to use the readiness flag instead of baseURL mocks.

@stalniy stalniy requested a review from a team as a code owner September 29, 2025 04:46
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 29, 2025

Walkthrough

AuthzHttpService was refactored to accept an injected HttpClient and expose isReady; DI registrations updated to construct it from the shared chain API HttpClient. ProviderService now looks up Provider by owner from the database instead of using ProviderHttpService. Web queries and tests now gate on authzHttpService.isReady.

Changes

Cohort / File(s) Summary
HTTP SDK: Authz service refactor
packages/http-sdk/src/authz/authz-http.service.ts
Remove HttpService inheritance; accept injected HttpClient in constructor; replace internal calls to use httpClient.get(...).then(extractData); add isReady getter using httpClient.defaults.baseURL.
API DI provider wiring
apps/api/src/core/providers/http-sdk.provider.ts
Move AuthzHttpService from axios-based SERVICES to NON_AXIOS_SERVICES; register it via factory that resolves CHAIN_API_HTTP_CLIENT (shared HttpClient).
ProviderService: DB-backed provider lookup
apps/api/src/provider/services/provider/provider.service.ts
Remove ProviderHttpService dependency; perform Provider.findOne({ where: { owner: providerAddress } }) for provider lookup; change sendManifest/getLeaseStatus to accept providerAddress; derive hostUri from DB entry; update error messages and identity construction.
Web DI wiring
apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx
Instantiate AuthzHttpService using shared di.chainApiHttpClient instead of constructing with baseURL/adapter.
Web queries & tests readiness gating
apps/deploy-web/src/queries/useGrantsQuery.ts, apps/deploy-web/src/queries/useGrantsQuery.spec.tsx, apps/deploy-web/src/queries/useBalancesQuery.ts
Change query enablement to check authzHttpService.isReady (instead of checking defaults.baseURL or getUri()); update tests to mock isReady: true while preserving API call expectations.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App
  participant DI as DI Container
  participant HC as HttpClient (CHAIN_API_HTTP_CLIENT)
  participant Authz as AuthzHttpService

  App->>DI: initialize()
  DI->>HC: createHttpClient(...)
  DI->>Authz: new AuthzHttpService(HC)
  App->>Authz: isReady?
  Authz-->>App: !!HC.defaults.baseURL
  Note over App,Authz: Queries enabled only when isReady is true
Loading
sequenceDiagram
  autonumber
  participant Caller
  participant ProvSvc as ProviderService
  participant DB as Database
  participant ProviderAPI as Provider API

  Caller->>ProvSvc: sendManifest(providerAddress, dseq, manifest, opts)
  ProvSvc->>DB: findOne({ owner: providerAddress })
  alt Provider found
    ProvSvc->>ProviderAPI: POST /manifest (hostUri from DB, identity.owner=providerAddress)
    ProviderAPI-->>ProvSvc: 2xx
    ProvSvc-->>Caller: success
  else Provider not found
    ProvSvc-->>Caller: throw "Provider not found: providerAddress"
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • ygrishajev
  • baktun14

Poem

I twitch my nose at shared requests,
A client snug within my chest.
DB carrots guide my way,
Authz hums: "I'm ready today."
Hops and headers, code's at rest 🥕🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the primary refactor by highlighting the adjustment of authz and provider services to handle blockchain unavailability, directly reflecting the main objective of adding a fallback to the indexer HTTP client. It is clear, specific, and avoids unnecessary detail or vagueness, making it easy for team members to understand the core change at a glance. By using the conventional "refactor" prefix and focusing on the central behavior change, it meets the criteria for an effective pull request title.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/chain-api-clients

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 48bfc3a and 1eb4342.

📒 Files selected for processing (7)
  • apps/api/src/core/providers/http-sdk.provider.ts (1 hunks)
  • apps/api/src/provider/services/provider/provider.service.ts (2 hunks)
  • apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1 hunks)
  • apps/deploy-web/src/queries/useBalancesQuery.ts (1 hunks)
  • apps/deploy-web/src/queries/useGrantsQuery.spec.tsx (6 hunks)
  • apps/deploy-web/src/queries/useGrantsQuery.ts (3 hunks)
  • packages/http-sdk/src/authz/authz-http.service.ts (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/deploy-web/src/queries/useGrantsQuery.spec.tsx
  • apps/deploy-web/src/queries/useGrantsQuery.ts
  • apps/api/src/provider/services/provider/provider.service.ts
  • apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Never use type any or cast to type any. Always define the proper TypeScript types.

Files:

  • apps/deploy-web/src/queries/useBalancesQuery.ts
  • apps/api/src/core/providers/http-sdk.provider.ts
  • packages/http-sdk/src/authz/authz-http.service.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code

Files:

  • apps/deploy-web/src/queries/useBalancesQuery.ts
  • apps/api/src/core/providers/http-sdk.provider.ts
  • packages/http-sdk/src/authz/authz-http.service.ts
🧬 Code graph analysis (2)
apps/api/src/core/providers/http-sdk.provider.ts (2)
packages/http-sdk/src/utils/httpClient.ts (1)
  • HttpClient (23-23)
packages/http-sdk/src/authz/authz-http.service.ts (1)
  • AuthzHttpService (56-219)
packages/http-sdk/src/authz/authz-http.service.ts (2)
packages/http-sdk/src/index.ts (1)
  • HttpClient (26-26)
packages/http-sdk/src/http/http.service.ts (2)
  • extractData (12-14)
  • extractData (17-19)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
🔇 Additional comments (3)
apps/deploy-web/src/queries/useBalancesQuery.ts (1)

13-13: Enabled guard matches the new service contract

Swapping to isReady keeps the query in lock-step with the refactored Authz service and avoids poking at implementation details—looks good.

apps/api/src/core/providers/http-sdk.provider.ts (1)

27-31: DI wiring stays consistent after the Authz refactor

Breaking out the HttpClient-driven services keeps the container coherent with the new constructors—registration logic remains tidy.

packages/http-sdk/src/authz/authz-http.service.ts (1)

62-197: Authz service now cleanly wraps the shared HttpClient

Constructor injection plus the isReady getter preserve existing behavior while decoupling from the old base class—well executed refactor.


Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Sep 29, 2025

Codecov Report

❌ Patch coverage is 38.46154% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.43%. Comparing base (9969a28) to head (1eb4342).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...src/provider/services/provider/provider.service.ts 0.00% 6 Missing ⚠️
.../src/context/ServicesProvider/ServicesProvider.tsx 0.00% 1 Missing ⚠️
apps/deploy-web/src/queries/useBalancesQuery.ts 0.00% 1 Missing ⚠️

❌ Your patch status has failed because the patch coverage (25.00%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1977      +/-   ##
==========================================
- Coverage   45.44%   45.43%   -0.02%     
==========================================
  Files        1003     1003              
  Lines       28446    28443       -3     
  Branches     7465     7449      -16     
==========================================
- Hits        12928    12922       -6     
+ Misses      15242    15155      -87     
- Partials      276      366      +90     
Flag Coverage Δ *Carryforward flag
api 81.60% <25.00%> (+<0.01%) ⬆️
deploy-web 23.69% <60.00%> (-0.03%) ⬇️
log-collector 75.35% <ø> (ø)
notifications 87.94% <ø> (ø)
provider-console 81.48% <ø> (ø) Carriedforward from 9969a28
provider-proxy 84.98% <ø> (ø) Carriedforward from 9969a28

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
apps/api/src/core/providers/http-sdk.provider.ts 100.00% <100.00%> (ø)
apps/deploy-web/src/queries/useGrantsQuery.ts 100.00% <100.00%> (ø)
.../src/context/ServicesProvider/ServicesProvider.tsx 65.38% <0.00%> (ø)
apps/deploy-web/src/queries/useBalancesQuery.ts 37.50% <0.00%> (ø)
...src/provider/services/provider/provider.service.ts 66.19% <0.00%> (-0.02%) ⬇️

... and 31 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/deploy-web/src/queries/useGrantsQuery.spec.tsx (2)

146-155: Remove as any; use deep mocks for Axios

Avoid any and shape Axios via jest-mock-extended’s deep mocks. As per coding guidelines.

-      const chainApiHttpClient = mock<AxiosInstance>({
-        defaults: { baseURL: "https://api.akash.network" },
-        get: jest.fn().mockResolvedValue({
-          data: {
-            allowances: mockData,
-            pagination: { next_key: null, total: mockData.length }
-          }
-        })
-      } as any);
+      // at top: import { mock, mockDeep, DeepMocked } from "jest-mock-extended";
+      const chainApiHttpClient: DeepMocked<AxiosInstance> = mockDeep<AxiosInstance>();
+      chainApiHttpClient.defaults.baseURL = "https://api.akash.network";
+      chainApiHttpClient.get.mockResolvedValue({
+        data: { allowances: mockData, pagination: { next_key: null, total: mockData.length } }
+      } as never);

172-181: Same here — drop as any for the second case

-      const chainApiHttpClient = mock<AxiosInstance>({
-        defaults: { baseURL: "https://api.akash.network" },
-        get: jest.fn().mockResolvedValue({
-          data: {
-            allowances: [],
-            pagination: { next_key: null, total: 0 }
-          }
-        })
-      } as any);
+      const chainApiHttpClient: DeepMocked<AxiosInstance> = mockDeep<AxiosInstance>();
+      chainApiHttpClient.defaults.baseURL = "https://api.akash.network";
+      chainApiHttpClient.get.mockResolvedValue({
+        data: { allowances: [], pagination: { next_key: null, total: 0 } }
+      } as never);
🧹 Nitpick comments (4)
apps/deploy-web/src/queries/useGrantsQuery.ts (2)

20-21: Gating via isReady looks right; avoid mutating incoming options

Prefer not mutating the caller’s options object. Compute enabled and pass it into useQuery so our gating logic always wins.

@@ export function useGranterGrants(...
-  options.enabled = options.enabled !== false && !!address && authzHttpService.isReady;
+  const enabled = options.enabled !== false && !!address && authzHttpService.isReady;
   return useQuery({
     queryKey: QueryKeys.getGranterGrants(address, page, offset),
     queryFn: () => authzHttpService.getPaginatedDepositDeploymentGrants({ granter: address, limit, offset }),
-    ...options
+    ...options,
+    enabled
   });
@@ export function useGranteeGrants(...
-  options.enabled = options.enabled !== false && !!address && authzHttpService.isReady;
+  const enabled = options.enabled !== false && !!address && authzHttpService.isReady;
   return useQuery({
-    queryKey: QueryKeys.getGranteeGrants(address || "UNDEFINED"),
+    queryKey: address ? QueryKeys.getGranteeGrants(address) : [],
     queryFn: () => authzHttpService.getAllDepositDeploymentGrants({ grantee: address, limit: 1000 }),
-    ...options
+    ...options,
+    enabled
   });
@@ export function useAllowancesIssued(...
-  options.enabled = options.enabled !== false && !!address && authzHttpService.isReady;
+  const enabled = options.enabled !== false && !!address && authzHttpService.isReady;
   return useQuery({
     queryKey: QueryKeys.getAllowancesIssued(address, page, offset),
     queryFn: () => authzHttpService.getPaginatedFeeAllowancesForGranter(address, limit, offset),
-    ...options
+    ...options,
+    enabled
   });

Also applies to: 32-33, 50-51


35-36: Unify queryKey pattern for empty address

You already use the “empty key disables” pattern elsewhere. Consider replacing "UNDEFINED" with [] for consistency, as shown in the diff above.

packages/http-sdk/src/authz/authz-http.service.ts (2)

60-61: Remove unused FEE_ALLOWANCE_TYPE

It’s declared but not referenced.

-  private readonly FEE_ALLOWANCE_TYPE: FeeAllowance["allowance"]["@type"] = "/cosmos.feegrant.v1beta1.BasicAllowance";

153-161: Tighten type of nextPageKey

Use a concrete type to self-document expectations from the API.

-  ): Promise<void> {
-    let nextPageKey: unknown;
+  ): Promise<void> {
+    let nextPageKey: string | null | undefined;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 384080c and 42a07a5.

📒 Files selected for processing (6)
  • apps/api/src/core/providers/http-sdk.provider.ts (1 hunks)
  • apps/api/src/provider/services/provider/provider.service.ts (2 hunks)
  • apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1 hunks)
  • apps/deploy-web/src/queries/useGrantsQuery.spec.tsx (6 hunks)
  • apps/deploy-web/src/queries/useGrantsQuery.ts (3 hunks)
  • packages/http-sdk/src/authz/authz-http.service.ts (8 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)

Don't use jest.mock() to mock dependencies in test files. Instead, use jest-mock-extended to create mocks and pass mocks as dependencies to the service under test.

**/*.spec.{ts,tsx}: Use setup function instead of beforeEach in test files
setup function must be at the bottom of the root describe block in test files
setup function creates an object under test and returns it
setup function should accept a single parameter with inline type definition
Don't use shared state in setup function
Don't specify return type of setup function

Files:

  • apps/deploy-web/src/queries/useGrantsQuery.spec.tsx
apps/{deploy-web,provider-console}/**/*.spec.tsx

📄 CodeRabbit inference engine (.cursor/rules/query-by-in-tests.mdc)

Use queryBy methods instead of getBy methods in test expectations in .spec.tsx files

Files:

  • apps/deploy-web/src/queries/useGrantsQuery.spec.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Never use type any or cast to type any. Always define the proper TypeScript types.

Files:

  • apps/deploy-web/src/queries/useGrantsQuery.spec.tsx
  • apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx
  • packages/http-sdk/src/authz/authz-http.service.ts
  • apps/api/src/provider/services/provider/provider.service.ts
  • apps/api/src/core/providers/http-sdk.provider.ts
  • apps/deploy-web/src/queries/useGrantsQuery.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code

Files:

  • apps/deploy-web/src/queries/useGrantsQuery.spec.tsx
  • apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx
  • packages/http-sdk/src/authz/authz-http.service.ts
  • apps/api/src/provider/services/provider/provider.service.ts
  • apps/api/src/core/providers/http-sdk.provider.ts
  • apps/deploy-web/src/queries/useGrantsQuery.ts
🧠 Learnings (1)
📚 Learning: 2025-07-21T08:24:27.953Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/query-by-in-tests.mdc:0-0
Timestamp: 2025-07-21T08:24:27.953Z
Learning: Applies to apps/{deploy-web,provider-console}/**/*.spec.tsx : Use `queryBy` methods instead of `getBy` methods in test expectations in `.spec.tsx` files

Applied to files:

  • apps/deploy-web/src/queries/useGrantsQuery.spec.tsx
🧬 Code graph analysis (4)
apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1)
packages/http-sdk/src/authz/authz-http.service.ts (1)
  • AuthzHttpService (56-219)
packages/http-sdk/src/authz/authz-http.service.ts (1)
packages/http-sdk/src/http/http.service.ts (2)
  • extractData (12-14)
  • extractData (17-19)
apps/api/src/provider/services/provider/provider.service.ts (3)
apps/indexer/drizzle/schema.ts (1)
  • provider (205-237)
apps/api/src/provider/services/provider/provider-proxy.service.ts (1)
  • ProviderIdentity (7-10)
apps/api/src/deployment/http-schemas/lease.schema.ts (1)
  • LeaseStatusResponse (53-53)
apps/api/src/core/providers/http-sdk.provider.ts (2)
packages/http-sdk/src/utils/httpClient.ts (1)
  • HttpClient (23-23)
packages/http-sdk/src/authz/authz-http.service.ts (1)
  • AuthzHttpService (56-219)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: Validate local packages
🔇 Additional comments (7)
apps/api/src/core/providers/http-sdk.provider.ts (2)

27-29: Authz removed from axios-based SERVICES — LGTM

This aligns with the refactor to a constructor that accepts HttpClient.


30-32: Add fallbackable HTTP client for NON_AXIOS_SERVICES
AuthzHttpService is registered with the plain CHAIN_API_HTTP_CLIENT in apps/api/src/core/providers/http-sdk.provider.ts; no fallback or indexer-based client was found—inject the Web app’s fallbackable HTTP client or a dedicated indexer client for Authz paths to handle blockchain downtime.

apps/deploy-web/src/queries/useGrantsQuery.spec.tsx (1)

31-33: Updated gating to isReady — LGTM

Mocks now set isReady: true; matches the production readiness check.

Also applies to: 49-51, 72-74, 91-93, 111-113, 130-132

apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1)

34-36: AuthzHttpService now built from shared chainApiHttpClient — LGTM

Matches the HttpClient-based service.

The fallback currently points to externalApiHttpClient with a TODO to switch to the indexer client. Confirm indexer has the required cosmos/authz endpoints, or adjust the fallback target.

packages/http-sdk/src/authz/authz-http.service.ts (3)

56-66: Constructor DI + isReady getter — LGTM

Clean separation from HttpService and clear readiness semantics.


68-71: Endpoints and pagination parsing — LGTM

Endpoints, params, and count_total parsing look correct; filters apply only valid/recognized grants.

Also applies to: 98-108, 111-121, 123-133, 161-171, 189-199


1-5: No .defaults.baseURL references on authzHttpService; drop repo-wide follow-up.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/api/src/provider/services/provider/provider.service.ts (1)

65-74: Preserve HTTP status on provider proxy errors; avoid any in catch

Generic throw new Error(...) collapses provider errors into 500s and the catch uses any. Narrow errors and map Axios failures to appropriate HTTP codes.

As per coding guidelines.

-      } catch (err: any) {
-        if (err.message?.includes("no lease for deployment") && i < this.MANIFEST_SEND_MAX_RETRIES) {
+      } catch (err: unknown) {
+        const axiosErr = AxiosError.isAxiosError(err) ? err : undefined;
+        const msg = axiosErr?.message ?? (err instanceof Error ? err.message : undefined);
+        if (msg?.includes("no lease for deployment") && i < this.MANIFEST_SEND_MAX_RETRIES) {
           await delay(this.MANIFEST_SEND_RETRY_DELAY);
           continue;
         }
-        const providerError = err instanceof AxiosError && err.response?.data;
-        assert(!providerError?.toLowerCase()?.includes("invalid manifest"), 400, err?.response?.data);
-
-        throw new Error(providerError || err);
+        const providerError = typeof axiosErr?.response?.data === "string" ? axiosErr.response.data : undefined;
+        assert(!providerError?.toLowerCase()?.includes("invalid manifest"), 400, providerError ?? msg);
+        if (axiosErr) {
+          const status =
+            axiosErr.response?.status ??
+            (axiosErr.code === "ECONNABORTED" ? 504 : 502);
+          assert(false, status, providerError ?? axiosErr.message);
+        }
+        assert(false, 500, msg ?? "Internal Server Error");
       }
packages/http-sdk/src/authz/authz-http.service.ts (1)

157-170: Type safety + omit null/undefined “pagination.key”.

Using unknown in params risks serialization of null/undefined; type it and include conditionally.

-    let nextPageKey: unknown;
+    let nextPageKey: string | undefined;
@@
-      const response = extractData(
-        await this.httpClient.get<DepositDeploymentGrantResponse>(`cosmos/authz/v1beta1/grants/${side}/${address}`, {
-          params: { "pagination.key": nextPageKey, "pagination.limit": options.limit }
-        })
-      );
+      const response = extractData(
+        await this.httpClient.get<DepositDeploymentGrantResponse>(`cosmos/authz/v1beta1/grants/${side}/${address}`, {
+          params: {
+            ...(nextPageKey ? { "pagination.key": nextPageKey } : {}),
+            "pagination.limit": options.limit
+          }
+        })
+      );
@@
-    } while (nextPageKey);
+    } while (nextPageKey);
🧹 Nitpick comments (8)
apps/api/src/provider/services/provider/provider.service.ts (3)

39-41: Also filter out deleted providers

Both lookups should exclude logically deleted providers to avoid using stale hostUri.

Apply this diff to both queries:

-const provider = await Provider.findOne({ where: { owner: providerAddress } });
+const provider = await Provider.findOne({ where: { owner: providerAddress, deletedHeight: null } });
-const provider = await Provider.findOne({
-  where: {
-    owner: providerAddress
-  }
-});
+const provider = await Provider.findOne({
+  where: { owner: providerAddress, deletedHeight: null }
+});

Also applies to: 85-91


51-76: Minor: remove truthy guard on result

fetchProviderUrl returning a falsy payload (e.g., empty object/string) would skip return. Prefer an unconditional return on success path.

-        if (result) return result;
+        return result;

36-49: DRY: factor provider lookup into a helper

findOne + 404 repeat across methods. Extract to a private helper for consistency and easier future changes (e.g., additional filters/joins).

Example:

private async getActiveProviderOr404(owner: string) {
  const p = await Provider.findOne({ where: { owner, deletedHeight: null } });
  assert(p, 404, `Provider ${owner} not found`);
  return p!;
}

Then use it in both methods.

Also applies to: 78-105

packages/http-sdk/src/authz/authz-http.service.ts (5)

64-66: Harden readiness check to avoid runtime if defaults is absent.

Guard against clients without Axios-like defaults.

-  get isReady(): boolean {
-    return !!this.httpClient.defaults.baseURL;
-  }
+  get isReady(): boolean {
+    return Boolean(this.httpClient.defaults?.baseURL);
+  }

100-108: Prefer status‑code check over brittle message matching for “not found”.

Indexer/chain nodes may vary error strings; key on 404 first, then (optional) message regex.

   async getFeeAllowanceForGranterAndGrantee(granter: string, grantee: string): Promise<FeeAllowance | undefined> {
     try {
       const response = extractData(await this.httpClient.get<FeeAllowanceResponse>(`cosmos/feegrant/v1beta1/allowance/${granter}/${grantee}`));
       return this.isValidFeeAllowance(response.allowance) ? response.allowance : undefined;
     } catch (error) {
-      if (isHttpError(error) && error.response?.data.message?.includes("fee-grant not found")) {
-        return undefined;
-      }
+      if (isHttpError(error)) {
+        if (error.response?.status === 404) return undefined;
+        const msg = error.response?.data?.message;
+        if (typeof msg === "string" && /fee-?grant not found/i.test(msg)) return undefined;
+      }
       throw error;
     }
   }

92-95: Specify radix in parseInt.

Avoid implicit radix; be explicit (10).

-        total: parseInt(allowances.pagination?.total || "0")
+        total: parseInt(allowances.pagination?.total || "0", 10)
-        total: parseInt(grants.pagination?.total || "0")
+        total: parseInt(grants.pagination?.total || "0", 10)

Also applies to: 201-205


208-214: More robust date handling (invalid strings, TZ).

Use parseISO and isValid to avoid surprises; aligns with date‑fns v4.1.0 behavior. Based on learnings.

-import { isFuture } from "date-fns";
+import { isFuture, parseISO, isValid as isValidDate } from "date-fns";
@@
-  private isValidFeeAllowance(allowance: FeeAllowance) {
-    return !allowance.allowance.expiration || isFuture(new Date(allowance.allowance.expiration));
-  }
+  private isValidFeeAllowance(allowance: FeeAllowance) {
+    const exp = allowance.allowance.expiration;
+    if (!exp) return true;
+    const dt = parseISO(exp);
+    return isValidDate(dt) && isFuture(dt);
+  }
@@
-  private isValidDepositDeploymentGrant(grant: ExactDepositDeploymentGrant) {
-    return this.isDepositDeploymentGrant(grant) && (!grant.expiration || isFuture(new Date(grant.expiration)));
-  }
+  private isValidDepositDeploymentGrant(grant: ExactDepositDeploymentGrant) {
+    if (!this.isDepositDeploymentGrant(grant)) return false;
+    if (!grant.expiration) return true;
+    const dt = parseISO(grant.expiration);
+    return isValidDate(dt) && isFuture(dt);
+  }

111-133: DRY: two nearly identical grant fetchers.

Both methods hit the same endpoint and differ only by predicate. Consider a private fetchGrants(granter, grantee) to reduce duplication.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 42a07a5 and 48bfc3a.

📒 Files selected for processing (3)
  • apps/api/src/provider/services/provider/provider.service.ts (2 hunks)
  • apps/deploy-web/src/queries/useBalancesQuery.ts (1 hunks)
  • packages/http-sdk/src/authz/authz-http.service.ts (8 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Never use type any or cast to type any. Always define the proper TypeScript types.

Files:

  • apps/deploy-web/src/queries/useBalancesQuery.ts
  • packages/http-sdk/src/authz/authz-http.service.ts
  • apps/api/src/provider/services/provider/provider.service.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code

Files:

  • apps/deploy-web/src/queries/useBalancesQuery.ts
  • packages/http-sdk/src/authz/authz-http.service.ts
  • apps/api/src/provider/services/provider/provider.service.ts
🧬 Code graph analysis (2)
packages/http-sdk/src/authz/authz-http.service.ts (2)
packages/http-sdk/src/index.ts (1)
  • HttpClient (26-26)
packages/http-sdk/src/http/http.service.ts (2)
  • extractData (12-14)
  • extractData (17-19)
apps/api/src/provider/services/provider/provider.service.ts (3)
apps/indexer/drizzle/schema.ts (1)
  • provider (205-237)
apps/api/src/provider/services/provider/provider-proxy.service.ts (1)
  • ProviderIdentity (7-10)
apps/api/src/deployment/http-schemas/lease.schema.ts (1)
  • LeaseStatusResponse (53-53)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
🔇 Additional comments (4)
apps/api/src/provider/services/provider/provider.service.ts (2)

39-46: Resolved: 404 on missing provider is correctly surfaced

Switch to DB lookup + assert(provider, 404, ...) fixes the earlier 500→404 issue. LGTM.


36-46: All sendManifest and getLeaseStatus calls in the API code now match the updated signatures; no further changes required.

apps/deploy-web/src/queries/useBalancesQuery.ts (1)

13-13: LGTM; readiness gating switched to isReady.

Looks consistent with the new DI. Verify that balances fetching truly depends on authz readiness (and not a different client) to avoid unnecessary gating.

packages/http-sdk/src/authz/authz-http.service.ts (1)

5-5: Ignore import path suggestion: HttpClient is exclusively exported from src/utils/httpClient.ts and every service already imports it correctly from “../utils/httpClient”; there is no “../http/http-client” module.

Likely an incorrect or invalid review comment.

@stalniy stalniy force-pushed the refactor/chain-api-clients branch from 48bfc3a to 1eb4342 Compare September 30, 2025 02:08
@stalniy stalniy merged commit 52ed240 into main Sep 30, 2025
62 of 63 checks passed
@stalniy stalniy deleted the refactor/chain-api-clients branch September 30, 2025 03:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments