feat(deployment): adds weekly deployment cost display for auto-topped-up deployments#2359
feat(deployment): adds weekly deployment cost display for auto-topped-up deployments#2359ygrishajev merged 2 commits intomainfrom
Conversation
WalkthroughAdds a weekly deployment cost feature end-to-end: new backend service method and controller endpoint, API schema and route, HTTP SDK client, frontend query and UI display, DI wiring, tests, and docs update for wallet reload triggers. Changes
Sequence Diagram(s)sequenceDiagram
participant Frontend as Frontend UI
participant Query as useWeeklyDeploymentCostQuery
participant HttpSdk as ManagedDeploymentHttpService
participant Api as DeploymentController
participant Service as DrainingDeploymentService
participant Db as Database/RPC
participant Balances as BalancesService
Frontend->>Query: request weekly cost
Query->>HttpSdk: getWeeklyDeploymentCost()
HttpSdk->>Api: GET /v1/weekly-cost
Api->>Service: calculateWeeklyDeploymentCost(userId, ability)
Service->>Service: authorize (AnyAbility)
Service->>Db: find auto-top-up settings & draining deployments
Db-->>Service: deployments & settings
Service->>Balances: toFiatAmount(per-deployment cost)
Balances-->>Service: fiat amounts
Service-->>Api: weeklyCost (number)
Api-->>HttpSdk: { data: { weeklyCost } }
HttpSdk-->>Query: weeklyCost
Query-->>Frontend: render weeklyCost
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #2359 +/- ##
==========================================
+ Coverage 51.32% 51.36% +0.03%
==========================================
Files 1060 1061 +1
Lines 28952 29016 +64
Branches 6372 6383 +11
==========================================
+ Hits 14860 14903 +43
- Misses 13696 13819 +123
+ Partials 396 294 -102
*This pull request uses carry forward flags. Click here to find out more.
🚀 New features to boost your workflow:
|
fbac70f to
320cbb0
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
apps/api/src/billing/services/wallet-balance-reload-check/README.md (1)
50-50: Consider rewording for readability.Three consecutive sentences begin with "When", which can make the text slightly repetitive. Consider varying the sentence structure for improved readability, e.g., starting one sentence with "For deployment auto top-up enablement, an immediate check..." or similar.
apps/api/src/deployment/http-schemas/deployment.schema.ts (1)
268-272: Schema follows existing patterns.The new schema is well-structured and consistent with other response schemas in this file. The description clearly documents the field's purpose.
Consider adding
.min(0)validation forweeklyCostto ensure the API always returns non-negative values, though this is optional for a response schema.export const GetWeeklyDeploymentCostResponseSchema = z.object({ data: z.object({ - weeklyCost: z.number().describe("Total weekly cost in USD for all deployments with auto top-up enabled") + weeklyCost: z.number().min(0).describe("Total weekly cost in USD for all deployments with auto top-up enabled") }) });apps/deploy-web/src/queries/useDeploymentQueries.ts (1)
7-16: LGTM with minor optimization opportunity.The hook implementation follows React Query patterns correctly. The query key is properly centralized, and type safety is maintained.
Minor optimization: The
return awaiton line 13 is redundant sincemanagedDeployment.getWeeklyDeploymentCost()already returns a Promise and the queryFn will handle the async resolution.Apply this diff to simplify:
queryFn: async () => { - return await managedDeployment.getWeeklyDeploymentCost(); + return managedDeployment.getWeeklyDeploymentCost(); }apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx (1)
135-143: LGTM!The weekly cost display is well-implemented with proper loading state handling and conditional rendering. The formatted currency presentation and descriptive text provide clear information to users about their ongoing deployment costs.
Minor note: The condition
weeklyCost !== undefined && weeklyCost > 0could be simplified to justweeklyCost > 0since the comparison already handles undefined (undefined > 0 is false). However, the explicit undefined check improves readability and intent, so this is purely a style preference.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
apps/api/src/billing/services/wallet-balance-reload-check/README.md(3 hunks)apps/api/src/deployment/controllers/deployment/deployment.controller.ts(3 hunks)apps/api/src/deployment/http-schemas/deployment.schema.ts(2 hunks)apps/api/src/deployment/routes/deployments/deployments.router.ts(2 hunks)apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts(5 hunks)apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts(3 hunks)apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx(6 hunks)apps/deploy-web/src/hooks/useFlag.tsx(1 hunks)apps/deploy-web/src/queries/index.ts(1 hunks)apps/deploy-web/src/queries/queryKeys.ts(1 hunks)apps/deploy-web/src/queries/useDeploymentQueries.ts(1 hunks)apps/deploy-web/src/services/app-di-container/app-di-container.ts(2 hunks)packages/http-sdk/src/deployment/managed-deployment-http.service.ts(1 hunks)packages/http-sdk/src/index.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
apps/api/src/deployment/http-schemas/deployment.schema.tsapps/deploy-web/src/queries/index.tsapps/deploy-web/src/queries/useDeploymentQueries.tspackages/http-sdk/src/index.tsapps/deploy-web/src/services/app-di-container/app-di-container.tsapps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.tsapps/api/src/deployment/controllers/deployment/deployment.controller.tsapps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsxapps/deploy-web/src/hooks/useFlag.tsxpackages/http-sdk/src/deployment/managed-deployment-http.service.tsapps/api/src/deployment/routes/deployments/deployments.router.tsapps/deploy-web/src/queries/queryKeys.tsapps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under testUse
setupfunction instead ofbeforeEachin test files. Thesetupfunction must be at the bottom of the rootdescribeblock, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
**/*.spec.{ts,tsx}: Use<Subject>.namein the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Use either a method name or a condition starting with 'when' for nested suite descriptions in tests
Use present simple, 3rd person singular for test descriptions without prepending 'should'
Files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
🧠 Learnings (8)
📚 Learning: 2025-11-25T17:45:49.180Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/query-by-in-tests.mdc:0-0
Timestamp: 2025-11-25T17:45:49.180Z
Learning: Applies to {apps/deploy-web,apps/provider-console}/**/*.spec.tsx : Use `queryBy` methods instead of `getBy` methods in test expectations
Applied to files:
apps/deploy-web/src/queries/index.tsapps/deploy-web/src/queries/useDeploymentQueries.ts
📚 Learning: 2025-06-03T15:06:34.211Z
Learnt from: baktun14
Repo: akash-network/console PR: 1428
File: apps/api/src/deployment/controllers/deployment/deployment.controller.ts:0-0
Timestamp: 2025-06-03T15:06:34.211Z
Learning: The `getByOwnerAndDseq` method in `apps/api/src/deployment/controllers/deployment/deployment.controller.ts` is intentionally public without the `Protected` decorator because it serves public blockchain data from an indexer, following the pattern of public blockchain APIs.
Applied to files:
apps/deploy-web/src/queries/index.tsapps/api/src/deployment/controllers/deployment/deployment.controller.ts
📚 Learning: 2025-11-19T16:13:43.249Z
Learnt from: stalniy
Repo: akash-network/console PR: 2255
File: apps/api/src/middlewares/privateMiddleware.ts:5-9
Timestamp: 2025-11-19T16:13:43.249Z
Learning: In the Akash Console API (apps/api), avoid resolving DI container dependencies at module scope (module initialization time) to prevent side effects. Instead, resolve dependencies inside functions/methods where they are actually used, even if this means resolving on every invocation, to maintain explicit control over when side effects occur and improve testability.
Applied to files:
apps/deploy-web/src/services/app-di-container/app-di-container.ts
📚 Learning: 2025-11-25T17:45:44.790Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/no-jest-mock.mdc:0-0
Timestamp: 2025-11-25T17:45:44.790Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use `jest.mock()` in test files. Instead, use `jest-mock-extended` to create mocks and pass mocks as dependencies to the service under test
Applied to files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
📚 Learning: 2025-11-19T15:15:07.283Z
Learnt from: ygrishajev
Repo: akash-network/console PR: 2254
File: apps/api/test/functional/sign-and-broadcast-tx.spec.ts:4-4
Timestamp: 2025-11-19T15:15:07.283Z
Learning: In the Akash Network Console project, when tests use native Node.js fetch (available in Node 18+), fetch-mock should be used for HTTP mocking instead of nock, as nock does not support intercepting native fetch calls. This applies to apps/api/test/functional/sign-and-broadcast-tx.spec.ts and any other tests using native fetch.
Applied to files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.
Applied to files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
📚 Learning: 2025-06-05T21:07:51.985Z
Learnt from: baktun14
Repo: akash-network/console PR: 1432
File: apps/deploy-web/src/components/deployments/DeploymentAlerts/DeploymentCloseAlert.tsx:38-38
Timestamp: 2025-06-05T21:07:51.985Z
Learning: The ContactPointSelect component in apps/deploy-web/src/components/alerts/ContactPointSelectForm/ContactPointSelect.tsx uses the useFormContext hook internally to connect to React Hook Form, so it doesn't need to be wrapped in a FormField component.
Applied to files:
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx
📚 Learning: 2025-07-28T10:40:13.595Z
Learnt from: stalniy
Repo: akash-network/console PR: 1480
File: apps/deploy-web/src/hooks/useFlag.tsx:0-0
Timestamp: 2025-07-28T10:40:13.595Z
Learning: In the Akash Network Console project, backend-specific feature flags are intentional and acceptable. The frontend FeatureFlag union type should only include flags that are actually used by the frontend, not all flags defined in the backend. Backend can have internal feature flags for backend-only functionality without requiring frontend synchronization.
Applied to files:
apps/deploy-web/src/hooks/useFlag.tsx
🧬 Code graph analysis (5)
apps/deploy-web/src/queries/useDeploymentQueries.ts (1)
apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1)
useServices(35-37)
apps/deploy-web/src/services/app-di-container/app-di-container.ts (3)
packages/http-sdk/src/deployment/managed-deployment-http.service.ts (1)
ManagedDeploymentHttpService(9-22)apps/deploy-web/src/services/auth/auth/auth.service.ts (1)
withUserToken(69-79)apps/deploy-web/src/services/auth/auth/interceptors.ts (1)
withUserToken(15-25)
packages/http-sdk/src/deployment/managed-deployment-http.service.ts (1)
packages/http-sdk/src/api-http/api-http.service.ts (1)
ApiHttpService(9-29)
apps/api/src/deployment/routes/deployments/deployments.router.ts (3)
apps/api/src/core/lib/create-route/create-route.ts (1)
createRoute(5-11)apps/api/src/core/services/openapi-docs/openapi-security.ts (1)
SECURITY_BEARER_OR_API_KEY(5-5)apps/api/src/deployment/http-schemas/deployment.schema.ts (1)
GetWeeklyDeploymentCostResponseSchema(268-272)
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (3)
apps/api/src/utils/constants.ts (1)
averageBlockCountInAnHour(8-8)apps/api/src/deployment/repositories/deployment-setting/deployment-setting.repository.ts (1)
AutoTopUpDeployment(18-24)apps/api/src/deployment/repositories/lease/lease.repository.ts (1)
DrainingDeploymentOutput(7-14)
🪛 LanguageTool
apps/api/src/billing/services/wallet-balance-reload-check/README.md
[style] ~50-~50: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...bled, the first check runs immediately. When deployment auto top-up is enabled, an i...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
⏰ 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). (8)
- 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: test-build
- GitHub Check: Validate local packages
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (19)
apps/deploy-web/src/hooks/useFlag.tsx (1)
6-8: LGTM!The dummy flag implementation correctly returns
falsespecifically for"console_embedded_login"while enabling all other flags whenNEXT_PUBLIC_UNLEASH_ENABLE_ALLis set. This prevents embedded login in development/testing scenarios where all flags are enabled.apps/api/src/billing/services/wallet-balance-reload-check/README.md (1)
59-80: Documentation update looks good.The sequence diagram clearly illustrates the new deployment auto top-up flow with
DeploymentSettingService.scheduleImmediate()andWalletReloadJobService.scheduleImmediate(). The branching logic is well-represented.apps/deploy-web/src/queries/index.ts (1)
9-9: LGTM!The new export follows the established pattern for re-exporting query modules.
packages/http-sdk/src/index.ts (1)
17-17: LGTM!The new export follows the established pattern and is logically grouped with the existing deployment HTTP service export.
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts (3)
345-390: Test helper follows the pattern, minor improvement possible.The
setupCalculateWeeklyCosthelper is well-structured and follows the project patterns. One observation:The
"userWallet" in inputcheck on line 352 will always be true whenuserWalletis explicitly passed (even asundefined), which is the intended behavior here. The tests correctly use this to differentiate between "not specified" (use default) and "explicitly undefined" (test missing wallet).
236-254: Comprehensive test coverage for calculateWeeklyDeploymentCost.The tests cover the main scenarios including:
- Standard calculation with multiple deployments
- Deployments closing after the 7-day window
- Missing user wallet
- Missing wallet address
- No deployments
- Null predictedClosedHeight
- Deployments closing at/before currentHeight
- Invalid blockRate values
518-561: Setup function correctly updated with BalancesService dependency.The
setupfunction properly instantiates theBalancesServicemock and passes it to theDrainingDeploymentServiceconstructor, following thejest-mock-extendedpattern required by the coding guidelines.apps/deploy-web/src/queries/queryKeys.ts (1)
78-79: LGTM!The new query key generator follows the established pattern and is appropriately placed with other related keys.
packages/http-sdk/src/deployment/managed-deployment-http.service.ts (1)
5-7: LGTM!The interface definition is clean and follows proper TypeScript conventions.
apps/api/src/deployment/routes/deployments/deployments.router.ts (1)
368-388: LGTM!The route definition and handler implementation follow established patterns in the codebase. The security requirement (SECURITY_BEARER_OR_API_KEY) is appropriate for a user-specific cost calculation endpoint.
apps/deploy-web/src/services/app-di-container/app-di-container.ts (1)
95-98: LGTM!The service wiring follows the established DI container pattern and is consistent with other HTTP service registrations in the container. The use of
withUserTokeninterceptor is appropriate for authenticated endpoints.apps/api/src/deployment/controllers/deployment/deployment.controller.ts (1)
104-108: LGTM!The controller method correctly applies authorization via the
@Protecteddecorator with "read" access, delegates to the service layer with proper user context and ability, and returns a correctly shaped response.apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx (2)
33-70: LGTM!The addition of a confirmation dialog before enabling/disabling auto-reload is a good UX improvement. The implementation correctly:
- Prompts with clear, context-specific messages
- Returns early if not confirmed, preventing unnecessary API calls
- Maintains proper error handling
- Includes
confirmin the dependency array
125-128: LGTM!The updated card header provides clear information about the auto-reload feature with an appropriate description of its behavior.
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (5)
133-153: LGTM!The refactoring of
calculateAllDeploymentCostUntilDateto use private helper methods (#findAutoTopUpDeploymentSettings,#findDrainingDeployments,#accumulateDeploymentCost) improves code organization and maintainability while preserving the original calculation logic.
163-192: LGTM!The
calculateWeeklyDeploymentCostmethod is well-implemented with:
- Proper authorization using ability-based access control on both wallet and deployment settings
- Correct weekly cost calculation (7 days × 24 hours × blocks per hour × block rate)
- Appropriate filtering for active deployments (predictedClosedHeight > currentHeight)
- Proper conversion to USD via BalancesService
- Safe handling of edge cases (no wallet, no settings, zero cost)
201-209: LGTM!The
#findAutoTopUpDeploymentSettingshelper properly validates wallet existence before querying deployment settings and returns a consistent empty array when validation fails.
220-223: LGTM!The
#findDrainingDeploymentshelper cleanly extracts a common pattern and delegates to the existingfindLeasesmethod.
233-242: LGTM!The
#accumulateDeploymentCosthelper provides a clean abstraction for cost accumulation with a callback pattern that allows flexible per-deployment cost calculations.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (2)
201-209: Redundant wallet lookup in#findAutoTopUpDeploymentSettings.The method queries
userWalletRepository.findOneBy({ address })and then checksuserWallet?.address, but theaddressparameter is already known. The check seems unnecessary since you're querying by address—if a record is found, it will have that address.This lookup may be intended to verify wallet existence, but the pattern differs from
calculateWeeklyDeploymentCostwhich usesaccessibleBy. Consider aligning the authorization approach or simplifying if the wallet existence check is redundant.async #findAutoTopUpDeploymentSettings(address: string): Promise<AutoTopUpDeployment[]> { const userWallet = await this.userWalletRepository.findOneBy({ address }); - if (!userWallet?.address) { + if (!userWallet) { return []; } return this.deploymentSettingRepository.findAutoTopUpDeploymentsByOwner(address); }
233-242: Consider usingreduceorPromise.allfor accumulation.The sequential
for...ofloop withawaitis correct but processes deployments one-at-a-time. Since the callback in current usages performs only synchronous calculations (no I/O), this could be simplified. If callbacks remain sync-only, consider making the callback synchronous to clarify intent.async #accumulateDeploymentCost( drainingDeployments: DrainingDeploymentOutput[], - callback: (deployment: DrainingDeploymentOutput) => Promise<number> + callback: (deployment: DrainingDeploymentOutput) => number ): Promise<number> { - let totalAmount = 0; - for (const deployment of drainingDeployments) { - totalAmount += await callback(deployment); - } - return totalAmount; + return drainingDeployments.reduce((total, deployment) => total + callback(deployment), 0); }apps/api/src/billing/services/wallet-balance-reload-check/README.md (1)
43-51: Documentation update accurately reflects the new trigger scenario.The addition of the deployment auto top-up scenario is well-documented. The sequence diagram clearly shows the new flow path.
Minor style note: Lines 45-50 have repetitive sentence starters ("When..."). Consider varying the structure for readability, e.g., "Immediately upon enabling deployment auto top-up..." or "After a user enables...".
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
apps/api/test/functional/__snapshots__/docs.spec.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (14)
apps/api/src/billing/services/wallet-balance-reload-check/README.md(3 hunks)apps/api/src/deployment/controllers/deployment/deployment.controller.ts(3 hunks)apps/api/src/deployment/http-schemas/deployment.schema.ts(2 hunks)apps/api/src/deployment/routes/deployments/deployments.router.ts(2 hunks)apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts(5 hunks)apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts(3 hunks)apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx(6 hunks)apps/deploy-web/src/hooks/useFlag.tsx(1 hunks)apps/deploy-web/src/queries/index.ts(1 hunks)apps/deploy-web/src/queries/queryKeys.ts(1 hunks)apps/deploy-web/src/queries/useDeploymentQueries.ts(1 hunks)apps/deploy-web/src/services/app-di-container/app-di-container.ts(2 hunks)packages/http-sdk/src/deployment/managed-deployment-http.service.ts(1 hunks)packages/http-sdk/src/index.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
- packages/http-sdk/src/deployment/managed-deployment-http.service.ts
- apps/api/src/deployment/controllers/deployment/deployment.controller.ts
- apps/deploy-web/src/services/app-di-container/app-di-container.ts
- apps/deploy-web/src/queries/index.ts
- apps/api/src/deployment/http-schemas/deployment.schema.ts
- apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx
- packages/http-sdk/src/index.ts
- apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
apps/api/src/deployment/routes/deployments/deployments.router.tsapps/deploy-web/src/hooks/useFlag.tsxapps/api/src/deployment/services/draining-deployment/draining-deployment.service.tsapps/deploy-web/src/queries/queryKeys.tsapps/deploy-web/src/queries/useDeploymentQueries.ts
🧠 Learnings (2)
📚 Learning: 2025-07-28T10:40:13.595Z
Learnt from: stalniy
Repo: akash-network/console PR: 1480
File: apps/deploy-web/src/hooks/useFlag.tsx:0-0
Timestamp: 2025-07-28T10:40:13.595Z
Learning: In the Akash Network Console project, backend-specific feature flags are intentional and acceptable. The frontend FeatureFlag union type should only include flags that are actually used by the frontend, not all flags defined in the backend. Backend can have internal feature flags for backend-only functionality without requiring frontend synchronization.
Applied to files:
apps/deploy-web/src/hooks/useFlag.tsx
📚 Learning: 2025-11-25T17:45:49.180Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/query-by-in-tests.mdc:0-0
Timestamp: 2025-11-25T17:45:49.180Z
Learning: Applies to {apps/deploy-web,apps/provider-console}/**/*.spec.tsx : Use `queryBy` methods instead of `getBy` methods in test expectations
Applied to files:
apps/deploy-web/src/queries/useDeploymentQueries.ts
🧬 Code graph analysis (3)
apps/api/src/deployment/routes/deployments/deployments.router.ts (3)
apps/api/src/core/lib/create-route/create-route.ts (1)
createRoute(5-11)apps/api/src/core/services/openapi-docs/openapi-security.ts (1)
SECURITY_BEARER_OR_API_KEY(5-5)apps/api/src/deployment/http-schemas/deployment.schema.ts (1)
GetWeeklyDeploymentCostResponseSchema(268-272)
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (3)
apps/api/src/utils/constants.ts (1)
averageBlockCountInAnHour(8-8)apps/api/src/deployment/repositories/deployment-setting/deployment-setting.repository.ts (1)
AutoTopUpDeployment(18-24)apps/api/src/deployment/repositories/lease/lease.repository.ts (1)
DrainingDeploymentOutput(7-14)
apps/deploy-web/src/queries/useDeploymentQueries.ts (1)
apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1)
useServices(35-37)
🪛 LanguageTool
apps/api/src/billing/services/wallet-balance-reload-check/README.md
[style] ~50-~50: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...bled, the first check runs immediately. When deployment auto top-up is enabled, an i...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
⏰ 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: validate / validate-app
- GitHub Check: test-build
- GitHub Check: test-build
🔇 Additional comments (7)
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (3)
1-31: LGTM on constructor and import changes.The new
BalancesServicedependency andAnyAbilityimport are properly integrated. The constructor maintains the existing pattern of dependency injection via tsyringe.
133-153: Refactored cost calculation logic is cleaner.The delegation to
#findAutoTopUpDeploymentSettingsand#findDrainingDeploymentsimproves readability. The#accumulateDeploymentCosthelper with callback pattern allows for flexible cost calculation strategies.
163-192: Verify the cost calculation logic for deployments that close before the week ends.The current logic at line 181 calculates cost for all deployments where
predictedClosedHeight > currentHeight, multiplying byblocksInAWeek. However, if a deployment is predicted to close mid-week, the user would be charged for a full week even though the deployment won't run that long.Consider whether this is intentional (charging for potential cost if auto top-up keeps it running) or if it should calculate only until
predictedClosedHeightfor deployments closing within the week.apps/deploy-web/src/queries/queryKeys.ts (1)
78-79: LGTM!The new
getWeeklyDeploymentCostKeyfollows the established pattern for static query key generators in this file. The simple array structure is appropriate for a user-scoped resource that doesn't require additional parameters.apps/deploy-web/src/queries/useDeploymentQueries.ts (1)
7-16: LGTM! Well-structured React Query hook.The hook correctly integrates with the services context and follows React Query v5 patterns. The
Omittype properly excludesqueryKeyandqueryFnfrom options.Minor note: The
async/awaitin thequeryFnis redundant sincegetWeeklyDeploymentCost()already returns a Promise, but this is stylistic and harmless.apps/api/src/deployment/routes/deployments/deployments.router.ts (1)
368-388: LGTM! Well-structured route definition.The new
/v1/weekly-costendpoint follows the established patterns in this router:
- Proper use of
createRoutewith security configuration- Consistent response schema integration
- Controller resolution via tsyringe container
- Appropriate HTTP method (GET) for a read operation
The route is properly secured with
SECURITY_BEARER_OR_API_KEY, consistent with other authenticated deployment endpoints.apps/deploy-web/src/hooks/useFlag.tsx (1)
6-8: Add inline comment explaining whyconsole_embedded_loginis excluded from all-flags-enabled mode.The
useDummyFlagfunction intentionally disables"console_embedded_login"even whenNEXT_PUBLIC_UNLEASH_ENABLE_ALLis active. While the README documents that theuseFlaghook is "patched" for consistent behavior during local development, the code lacks an inline explanation for why this specific flag is excluded. Add a brief comment (e.g., "embedded login is security-sensitive and must remain disabled in all-flags-enabled dev mode") to clarify the intentional behavior for future maintainers.⛔ Skipped due to learnings
Learnt from: stalniy Repo: akash-network/console PR: 1480 File: apps/deploy-web/src/hooks/useFlag.tsx:0-0 Timestamp: 2025-07-28T10:40:13.595Z Learning: In the Akash Network Console project, backend-specific feature flags are intentional and acceptable. The frontend FeatureFlag union type should only include flags that are actually used by the frontend, not all flags defined in the backend. Backend can have internal feature flags for backend-only functionality without requiring frontend synchronization.
320cbb0 to
4caede8
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
apps/api/src/billing/services/wallet-balance-reload-check/README.md (1)
50-50: Reword consecutive "When" sentences for better flow.The static analysis tool flagged three successive sentences beginning with "When." Consider restructuring line 50 to vary sentence openers and improve readability.
-When auto-reload is enabled, the first check runs immediately. When deployment auto top-up is enabled, an immediate check is scheduled to ensure the wallet balance can cover the new deployment costs. Subsequent checks run on a daily schedule. Immediate triggers (deployments/deposits) ensure the balance is checked right after spending or depositing funds, rather than waiting for the next scheduled check. +When auto-reload is enabled, the first check runs immediately. If deployment auto top-up is enabled, an immediate check is scheduled to ensure the wallet balance can cover the new deployment costs. Subsequent checks run on a daily schedule. Immediate triggers (deployments/deposits) ensure the balance is checked right after spending or depositing funds, rather than waiting for the next scheduled check.apps/deploy-web/src/hooks/useFlag.tsx (1)
6-8: Consider renaming parameter for consistency.The implementation correctly enables all flags except
console_embedded_loginwhen the enable-all environment variable is set. However, the parameter namenameis inconsistent with the type definition on line 11, which usesflag.Apply this diff for consistency:
-const useDummyFlag: FeatureFlagHook = name => { - return name !== "console_embedded_login"; +const useDummyFlag: FeatureFlagHook = flag => { + return flag !== "console_embedded_login"; };apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts (1)
378-383: Consider more realistic mock behavior for fiat conversion.The mock returns the same
expectedFiatAmountfor any non-zero uakt amount. While this works for single-deployment scenarios, the test at lines 237-254 sums costs from multiple deployments (blockRate 50 and 75) but receives the same flat fiat amount. This doesn't reflect real aggregation behavior.Consider a proportional mock implementation:
-baseSetup.balancesService.toFiatAmount.mockImplementation(async (uaktAmount: number) => { - if (uaktAmount === 0) { - return 0; - } - return input.expectedFiatAmount ?? 0; -}); +baseSetup.balancesService.toFiatAmount.mockImplementation(async (uaktAmount: number) => { + // Use a simple conversion rate for testing, e.g., 1 uakt = 0.0001 USD + return uaktAmount * 0.0001; +});Then update test assertions to calculate expected values based on actual block rates.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
apps/api/test/functional/__snapshots__/docs.spec.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (14)
apps/api/src/billing/services/wallet-balance-reload-check/README.md(3 hunks)apps/api/src/deployment/controllers/deployment/deployment.controller.ts(3 hunks)apps/api/src/deployment/http-schemas/deployment.schema.ts(2 hunks)apps/api/src/deployment/routes/deployments/deployments.router.ts(2 hunks)apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts(5 hunks)apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts(3 hunks)apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx(6 hunks)apps/deploy-web/src/hooks/useFlag.tsx(1 hunks)apps/deploy-web/src/queries/index.ts(1 hunks)apps/deploy-web/src/queries/queryKeys.ts(1 hunks)apps/deploy-web/src/queries/useDeploymentQueries.ts(1 hunks)apps/deploy-web/src/services/app-di-container/app-di-container.ts(2 hunks)packages/http-sdk/src/deployment/managed-deployment-http.service.ts(1 hunks)packages/http-sdk/src/index.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/deploy-web/src/queries/index.ts
- apps/deploy-web/src/queries/useDeploymentQueries.ts
- apps/deploy-web/src/services/app-di-container/app-di-container.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
packages/http-sdk/src/index.tspackages/http-sdk/src/deployment/managed-deployment-http.service.tsapps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsxapps/api/src/deployment/routes/deployments/deployments.router.tsapps/api/src/deployment/controllers/deployment/deployment.controller.tsapps/deploy-web/src/hooks/useFlag.tsxapps/api/src/deployment/http-schemas/deployment.schema.tsapps/api/src/deployment/services/draining-deployment/draining-deployment.service.tsapps/deploy-web/src/queries/queryKeys.tsapps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under testUse
setupfunction instead ofbeforeEachin test files. Thesetupfunction must be at the bottom of the rootdescribeblock, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
**/*.spec.{ts,tsx}: Use<Subject>.namein the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Use either a method name or a condition starting with 'when' for nested suite descriptions in tests
Use present simple, 3rd person singular for test descriptions without prepending 'should'
Files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
🧠 Learnings (6)
📚 Learning: 2025-06-05T21:07:51.985Z
Learnt from: baktun14
Repo: akash-network/console PR: 1432
File: apps/deploy-web/src/components/deployments/DeploymentAlerts/DeploymentCloseAlert.tsx:38-38
Timestamp: 2025-06-05T21:07:51.985Z
Learning: The ContactPointSelect component in apps/deploy-web/src/components/alerts/ContactPointSelectForm/ContactPointSelect.tsx uses the useFormContext hook internally to connect to React Hook Form, so it doesn't need to be wrapped in a FormField component.
Applied to files:
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx
📚 Learning: 2025-06-03T15:06:34.211Z
Learnt from: baktun14
Repo: akash-network/console PR: 1428
File: apps/api/src/deployment/controllers/deployment/deployment.controller.ts:0-0
Timestamp: 2025-06-03T15:06:34.211Z
Learning: The `getByOwnerAndDseq` method in `apps/api/src/deployment/controllers/deployment/deployment.controller.ts` is intentionally public without the `Protected` decorator because it serves public blockchain data from an indexer, following the pattern of public blockchain APIs.
Applied to files:
apps/api/src/deployment/controllers/deployment/deployment.controller.ts
📚 Learning: 2025-07-28T10:40:13.595Z
Learnt from: stalniy
Repo: akash-network/console PR: 1480
File: apps/deploy-web/src/hooks/useFlag.tsx:0-0
Timestamp: 2025-07-28T10:40:13.595Z
Learning: In the Akash Network Console project, backend-specific feature flags are intentional and acceptable. The frontend FeatureFlag union type should only include flags that are actually used by the frontend, not all flags defined in the backend. Backend can have internal feature flags for backend-only functionality without requiring frontend synchronization.
Applied to files:
apps/deploy-web/src/hooks/useFlag.tsx
📚 Learning: 2025-11-25T17:45:44.790Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/no-jest-mock.mdc:0-0
Timestamp: 2025-11-25T17:45:44.790Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use `jest.mock()` in test files. Instead, use `jest-mock-extended` to create mocks and pass mocks as dependencies to the service under test
Applied to files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
📚 Learning: 2025-11-19T15:15:07.283Z
Learnt from: ygrishajev
Repo: akash-network/console PR: 2254
File: apps/api/test/functional/sign-and-broadcast-tx.spec.ts:4-4
Timestamp: 2025-11-19T15:15:07.283Z
Learning: In the Akash Network Console project, when tests use native Node.js fetch (available in Node 18+), fetch-mock should be used for HTTP mocking instead of nock, as nock does not support intercepting native fetch calls. This applies to apps/api/test/functional/sign-and-broadcast-tx.spec.ts and any other tests using native fetch.
Applied to files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.
Applied to files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
🧬 Code graph analysis (5)
packages/http-sdk/src/deployment/managed-deployment-http.service.ts (1)
packages/http-sdk/src/api-http/api-http.service.ts (1)
ApiHttpService(9-29)
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx (3)
apps/deploy-web/src/queries/useDeploymentQueries.ts (1)
useWeeklyDeploymentCostQuery(7-16)apps/deploy-web/src/queries/useWalletSettingsQueries.tsx (1)
useWalletSettingsMutations(20-56)packages/ui/context/PopupProvider/PopupProvider.tsx (1)
usePopup(140-146)
apps/api/src/deployment/routes/deployments/deployments.router.ts (3)
apps/api/src/core/lib/create-route/create-route.ts (1)
createRoute(5-11)apps/api/src/core/services/openapi-docs/openapi-security.ts (1)
SECURITY_BEARER_OR_API_KEY(5-5)apps/api/src/deployment/http-schemas/deployment.schema.ts (1)
GetWeeklyDeploymentCostResponseSchema(268-272)
apps/api/src/deployment/controllers/deployment/deployment.controller.ts (1)
apps/api/src/deployment/http-schemas/deployment.schema.ts (1)
GetWeeklyDeploymentCostResponse(286-286)
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts (1)
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (3)
address(201-209)deploymentSettings(220-223)drainingDeployments(233-242)
🪛 LanguageTool
apps/api/src/billing/services/wallet-balance-reload-check/README.md
[style] ~50-~50: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...bled, the first check runs immediately. When deployment auto top-up is enabled, an i...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
⏰ 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). (8)
- 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: test-build
- GitHub Check: Validate local packages
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (17)
apps/api/src/billing/services/wallet-balance-reload-check/README.md (1)
43-80: Documentation of new deployment auto top-up scenario is clear and well-integrated.The new trigger scenario is properly documented across the list, narrative, and sequence diagram. The logic is easy to follow: immediate check when auto top-up is enabled ensures wallet balance covers new deployment costs before proceeding. The placement as scenario #2 and the [OR] branching in the diagram accurately represent the control flow.
apps/deploy-web/src/queries/queryKeys.ts (1)
78-79: LGTM!The new query key follows the established pattern in the class and is appropriately placed near other deployment-related keys.
apps/api/src/deployment/http-schemas/deployment.schema.ts (2)
268-272: LGTM!The schema follows the established pattern of wrapping response data in a
dataobject and includes a clear description for the OpenAPI documentation.
286-286: LGTM!Type export is properly inferred from the schema.
packages/http-sdk/src/deployment/managed-deployment-http.service.ts (2)
5-7: LGTM!The interface properly types the extracted API data structure with
weeklyCostas a number.
9-21: LGTM!The service class correctly extends
ApiHttpService, usesextractApiDatato unwrap the response, and returns theweeklyCostvalue. The JSDoc accurately documents that the return value is in USD.packages/http-sdk/src/index.ts (1)
17-17: LGTM!The new service is properly exported from the SDK's public API, following the established pattern and positioned logically next to the related deployment service.
apps/api/src/deployment/routes/deployments/deployments.router.ts (2)
18-18: LGTM!Import correctly added to the schema imports block.
368-388: LGTM!The route definition follows the established patterns in the file:
- Uses
createRoutehelper consistently- Properly applies
SECURITY_BEARER_OR_API_KEYfor authentication- Handler uses the
container.resolvepattern for dependency injection- Response schema is correctly referenced
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts (1)
529-529: LGTM! Proper mock setup and dependency injection.The BalancesService is correctly mocked using
jest-mock-extendedand properly wired into the service constructor and test fixtures.Also applies to: 545-546, 557-557
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx (3)
33-70: Excellent UX improvement with confirmation dialog.The confirmation flow ensures users understand the implications of enabling/disabling auto-reload before making changes. The implementation correctly uses
usePopupand properly updates the dependency array to includeconfirm.
135-143: LGTM! Clean conditional rendering of weekly cost.The weekly cost is displayed only when loaded and greater than zero, which correctly handles both loading states and cases where no auto-topped-up deployments exist. The currency formatting using
FormattedNumberis appropriate.
125-134: LGTM! Layout adjustments accommodate new content.The header layout changes properly accommodate the CardDescription and vertical arrangement of the Switch with the weekly cost display below it.
apps/api/src/deployment/controllers/deployment/deployment.controller.ts (1)
104-108: LGTM! Clean controller implementation.The new method follows the established patterns in this controller:
- Appropriate authorization decorator (
@Protectedwith read on UserWallet)- Delegates business logic to the service layer
- Properly passes user context (userId and ability)
- Returns response in the expected schema format
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (3)
163-192: LGTM! Comprehensive weekly cost calculation with proper authorization.The implementation demonstrates several good practices:
- Ability-based access control for wallet and deployment settings (lines 164, 170)
- Clever use of
Number.MAX_SAFE_INTEGERto include all deployments regardless of predicted closure (line 178)- Robust validation: null checks, currentHeight comparison, and blockRate > 0 (line 181)
- Performance optimization: early return when cost is zero avoids unnecessary fiat conversion (lines 187-189)
- Clear documentation explaining the 7-day calculation window
133-153: LGTM! Clean refactoring with reusable helpers.The refactoring extracts common patterns into private helpers (
#findAutoTopUpDeploymentSettings,#findDrainingDeployments,#accumulateDeploymentCost) that are now shared betweencalculateAllDeploymentCostUntilDateand the newcalculateWeeklyDeploymentCostmethod. This improves maintainability while preserving the original behavior.
194-242: LGTM! Well-designed private helper methods.The three new private helpers are well-structured:
#findAutoTopUpDeploymentSettings: Validates wallet existence before querying (defensive programming)#findDrainingDeployments: Simple extraction and delegation to existingfindLeasesmethod#accumulateDeploymentCost: Generic accumulator accepting a callback for flexible cost calculationAll helpers are properly documented with JSDoc and follow single-responsibility principle.
…-up deployments - Adds GET /v1/weekly-cost API endpoint returning USD cost - Calculates weekly cost using DrainingDeploymentService with BalancesService conversion - Displays weekly cost in AccountOverview UI with formal description - Adds ManagedDeploymentHttpService for console API endpoints - Adds comprehensive unit tests with BalancesService mocking - Updates documentation for auto top-up immediate check scenario refs #1779
4caede8 to
2ff2a3e
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx (1)
125-143: Consider extracting the weekly cost display into a separate component.The conditional rendering logic for the weekly cost section is clear and handles loading/empty states well. However, wrapping the Switch in an extra
flex items-center justify-betweendiv (line 132-134) leaves the Switch isolated without any visible label or adjacent element to justify thejustify-between.- <div className="flex items-center justify-between"> - <Switch checked={walletSettings?.autoReloadEnabled ?? false} onCheckedChange={toggleAutoReload} disabled={isReloadChangeDisabled} /> - </div> + <Switch checked={walletSettings?.autoReloadEnabled ?? false} onCheckedChange={toggleAutoReload} disabled={isReloadChangeDisabled} />apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (1)
233-242: Consider usingreduceorPromise.allfor accumulation.The sequential
for...ofloop withawaitworks correctly but processes deployments one at a time. If the callback doesn't have ordering dependencies, parallel execution could improve performance for large deployment lists.async #accumulateDeploymentCost( drainingDeployments: DrainingDeploymentOutput[], callback: (deployment: DrainingDeploymentOutput) => Promise<number> ): Promise<number> { - let totalAmount = 0; - for (const deployment of drainingDeployments) { - totalAmount += await callback(deployment); - } - return totalAmount; + const costs = await Promise.all(drainingDeployments.map(callback)); + return costs.reduce((sum, cost) => sum + cost, 0); }apps/api/src/billing/services/wallet-balance-reload-check/README.md (1)
50-50: Consider rephrasing to avoid repetitive sentence structure.Three consecutive sentences begin with "When", which impacts readability. Consider combining or restructuring.
Apply this diff to improve the flow:
-When auto-reload is enabled, the first check runs immediately. When deployment auto top-up is enabled, an immediate check is scheduled to ensure the wallet balance can cover the new deployment costs. Subsequent checks run on a daily schedule. Immediate triggers (deployments/deposits) ensure the balance is checked right after spending or depositing funds, rather than waiting for the next scheduled check. +The first check runs immediately when auto-reload is enabled. Enabling deployment auto top-up schedules an immediate check to ensure the wallet balance can cover the new deployment costs. Subsequent checks run on a daily schedule, with immediate triggers (deployments/deposits) ensuring the balance is checked right after spending or depositing funds rather than waiting for the next scheduled check.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
apps/api/test/functional/__snapshots__/docs.spec.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (13)
apps/api/src/billing/services/wallet-balance-reload-check/README.md(3 hunks)apps/api/src/deployment/controllers/deployment/deployment.controller.ts(3 hunks)apps/api/src/deployment/http-schemas/deployment.schema.ts(2 hunks)apps/api/src/deployment/routes/deployments/deployments.router.ts(2 hunks)apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts(5 hunks)apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts(3 hunks)apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx(6 hunks)apps/deploy-web/src/queries/index.ts(1 hunks)apps/deploy-web/src/queries/queryKeys.ts(1 hunks)apps/deploy-web/src/queries/useDeploymentQueries.ts(1 hunks)apps/deploy-web/src/services/app-di-container/app-di-container.ts(2 hunks)packages/http-sdk/src/deployment/managed-deployment-http.service.ts(1 hunks)packages/http-sdk/src/index.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- packages/http-sdk/src/index.ts
- apps/deploy-web/src/queries/queryKeys.ts
- packages/http-sdk/src/deployment/managed-deployment-http.service.ts
- apps/api/src/deployment/controllers/deployment/deployment.controller.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.tsapps/deploy-web/src/queries/index.tsapps/api/src/deployment/http-schemas/deployment.schema.tsapps/api/src/deployment/routes/deployments/deployments.router.tsapps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsxapps/deploy-web/src/services/app-di-container/app-di-container.tsapps/api/src/deployment/services/draining-deployment/draining-deployment.service.tsapps/deploy-web/src/queries/useDeploymentQueries.ts
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under testUse
setupfunction instead ofbeforeEachin test files. Thesetupfunction must be at the bottom of the rootdescribeblock, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
**/*.spec.{ts,tsx}: Use<Subject>.namein the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Use either a method name or a condition starting with 'when' for nested suite descriptions in tests
Use present simple, 3rd person singular for test descriptions without prepending 'should'
Files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
🧠 Learnings (7)
📚 Learning: 2025-11-25T17:45:44.790Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/no-jest-mock.mdc:0-0
Timestamp: 2025-11-25T17:45:44.790Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use `jest.mock()` in test files. Instead, use `jest-mock-extended` to create mocks and pass mocks as dependencies to the service under test
Applied to files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
📚 Learning: 2025-11-19T15:15:07.283Z
Learnt from: ygrishajev
Repo: akash-network/console PR: 2254
File: apps/api/test/functional/sign-and-broadcast-tx.spec.ts:4-4
Timestamp: 2025-11-19T15:15:07.283Z
Learning: In the Akash Network Console project, when tests use native Node.js fetch (available in Node 18+), fetch-mock should be used for HTTP mocking instead of nock, as nock does not support intercepting native fetch calls. This applies to apps/api/test/functional/sign-and-broadcast-tx.spec.ts and any other tests using native fetch.
Applied to files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.
Applied to files:
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts
📚 Learning: 2025-11-25T17:45:49.180Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/query-by-in-tests.mdc:0-0
Timestamp: 2025-11-25T17:45:49.180Z
Learning: Applies to {apps/deploy-web,apps/provider-console}/**/*.spec.tsx : Use `queryBy` methods instead of `getBy` methods in test expectations
Applied to files:
apps/deploy-web/src/queries/index.tsapps/deploy-web/src/queries/useDeploymentQueries.ts
📚 Learning: 2025-06-03T15:06:34.211Z
Learnt from: baktun14
Repo: akash-network/console PR: 1428
File: apps/api/src/deployment/controllers/deployment/deployment.controller.ts:0-0
Timestamp: 2025-06-03T15:06:34.211Z
Learning: The `getByOwnerAndDseq` method in `apps/api/src/deployment/controllers/deployment/deployment.controller.ts` is intentionally public without the `Protected` decorator because it serves public blockchain data from an indexer, following the pattern of public blockchain APIs.
Applied to files:
apps/deploy-web/src/queries/index.ts
📚 Learning: 2025-06-05T21:07:51.985Z
Learnt from: baktun14
Repo: akash-network/console PR: 1432
File: apps/deploy-web/src/components/deployments/DeploymentAlerts/DeploymentCloseAlert.tsx:38-38
Timestamp: 2025-06-05T21:07:51.985Z
Learning: The ContactPointSelect component in apps/deploy-web/src/components/alerts/ContactPointSelectForm/ContactPointSelect.tsx uses the useFormContext hook internally to connect to React Hook Form, so it doesn't need to be wrapped in a FormField component.
Applied to files:
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx
📚 Learning: 2025-11-19T16:13:43.249Z
Learnt from: stalniy
Repo: akash-network/console PR: 2255
File: apps/api/src/middlewares/privateMiddleware.ts:5-9
Timestamp: 2025-11-19T16:13:43.249Z
Learning: In the Akash Console API (apps/api), avoid resolving DI container dependencies at module scope (module initialization time) to prevent side effects. Instead, resolve dependencies inside functions/methods where they are actually used, even if this means resolving on every invocation, to maintain explicit control over when side effects occur and improve testability.
Applied to files:
apps/deploy-web/src/services/app-di-container/app-di-container.ts
🧬 Code graph analysis (4)
apps/api/src/deployment/routes/deployments/deployments.router.ts (3)
apps/api/src/core/lib/create-route/create-route.ts (1)
createRoute(5-11)apps/api/src/core/services/openapi-docs/openapi-security.ts (1)
SECURITY_BEARER_OR_API_KEY(5-5)apps/api/src/deployment/http-schemas/deployment.schema.ts (1)
GetWeeklyDeploymentCostResponseSchema(268-272)
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx (4)
apps/deploy-web/src/queries/useDeploymentQueries.ts (1)
useWeeklyDeploymentCostQuery(7-16)apps/deploy-web/src/queries/useWalletSettingsQueries.tsx (1)
useWalletSettingsMutations(20-56)packages/ui/context/PopupProvider/PopupProvider.tsx (1)
usePopup(140-146)packages/ui/components/switch.tsx (1)
Switch(52-52)
apps/deploy-web/src/services/app-di-container/app-di-container.ts (3)
packages/http-sdk/src/deployment/managed-deployment-http.service.ts (1)
ManagedDeploymentHttpService(9-22)apps/deploy-web/src/services/auth/auth/auth.service.ts (1)
withUserToken(69-79)apps/deploy-web/src/services/auth/auth/interceptors.ts (1)
withUserToken(15-25)
apps/deploy-web/src/queries/useDeploymentQueries.ts (2)
apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1)
useServices(35-37)apps/deploy-web/src/queries/queryKeys.ts (1)
QueryKeys(1-127)
🪛 LanguageTool
apps/api/src/billing/services/wallet-balance-reload-check/README.md
[style] ~50-~50: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...bled, the first check runs immediately. When deployment auto top-up is enabled, an i...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
⏰ 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). (8)
- 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: test-build
- GitHub Check: Validate local packages
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (21)
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx (3)
3-4: LGTM!Imports are correctly added for the new UI components and confirmation popup hook.
23-25: LGTM!Query hook and popup confirmation are properly destructured and used.
33-69: LGTM!The confirmation flow is well implemented:
- Clear user-facing messages for enable/disable scenarios
- Early return on cancel prevents unintended state changes
- Dependency array correctly includes
confirmapps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (4)
1-14: LGTM!Imports are correctly organized with new dependencies for authorization and balance conversion.
27-31: LGTM!Constructor properly extended to include the new
BalancesServicedependency for fiat conversion.
163-192: Well-structured weekly cost calculation.The method correctly:
- Applies authorization via
abilityparameter- Returns early with 0 for missing wallet/deployments
- Uses
Number.MAX_SAFE_INTEGERforclosureHeightto include all active deployments regardless of when they would close- Converts the final uAKT amount to fiat
201-209: Potential redundant wallet lookup.
#findAutoTopUpDeploymentSettingslooks up the user wallet by address (line 202), but the caller (calculateAllDeploymentCostUntilDate) already receives an address parameter. The wallet existence check could fail silently if the wallet doesn't exist, which may hide issues.Consider whether this validation is intentional or if the caller should be responsible for ensuring the wallet exists.
apps/deploy-web/src/queries/index.ts (1)
9-9: LGTM!Re-export follows the established pattern for query module exports.
apps/deploy-web/src/queries/useDeploymentQueries.ts (1)
7-16: LGTM!Well-structured React Query hook that:
- Properly types the query result as
number- Uses
Omitto prevent overridingqueryKey/queryFn- Follows the established pattern from other query hooks in the codebase
apps/deploy-web/src/services/app-di-container/app-di-container.ts (2)
7-7: LGTM!Import correctly added alongside other HTTP service imports.
95-98: LGTM!The
managedDeploymentservice follows the established pattern:
- Lazily instantiated via factory function (aligned with retrieved learning about avoiding module-scope resolution)
- Uses
withUserTokeninterceptor for authenticated requests- Mirrors the
deploymentSettingservice configurationapps/api/src/deployment/http-schemas/deployment.schema.ts (2)
268-272: LGTM!The schema is well-defined with a clear description and follows the established patterns in the file.
286-286: LGTM!The type export follows the correct pattern used for other response types in this file.
apps/api/src/deployment/routes/deployments/deployments.router.ts (2)
18-18: LGTM!Import is correctly placed with other schema imports.
368-388: LGTM!The route implementation follows the established patterns in this file with appropriate security, proper OpenAPI documentation, and correct controller method invocation.
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.spec.ts (6)
3-3: LGTM!Type import for AnyAbility is correctly used in the test setup at line 353.
10-10: LGTM!Type import for BalancesService is correctly used for mocking at line 529.
236-391: LGTM! Comprehensive test coverage.The test suite follows all coding guidelines and provides excellent coverage:
- Uses
jest-mock-extendedfor mocking (nojest.mock())- Helper function
setupCalculateWeeklyCostwith inline types- Present simple, 3rd person singular test descriptions
- Covers all edge cases: valid calculations, late closures, missing wallet/address, empty deployments, null heights, invalid block rates
The
balancesService.toFiatAmountmock implementation is appropriately simplified for unit testing.
529-529: LGTM!BalancesService is properly mocked using
jest-mock-extendedas per coding guidelines.
545-546: LGTM!The balancesService dependency is correctly passed to the DrainingDeploymentService constructor.
557-557: LGTM!The balancesService is correctly included in the setup return object for test access.
packages/http-sdk/src/deployment/managed-deployment-http.service.ts
Outdated
Show resolved
Hide resolved
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts
Show resolved
Hide resolved
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (2)
233-242: Consider removing unnecessaryasynckeyword.Since the callback now returns
numbersynchronously, this method doesn't need to be async. The previous review suggestingPromise.allwas for when the callback was async.- async #accumulateDeploymentCost( + #accumulateDeploymentCost( drainingDeployments: DrainingDeploymentOutput[], callback: (deployment: DrainingDeploymentOutput) => number - ): Promise<number> { + ): number { let totalAmount = 0; for (const deployment of drainingDeployments) { totalAmount += callback(deployment); } return totalAmount; }You would also need to remove the
awaiton lines 146 and 180 when calling this method.
201-209: Minor redundancy in validation.The method queries
userWalletRepository.findOneBy({ address })and then checks!userWallet?.address. Since you're already querying by the address, if a wallet is found, it will have that address. The check effectively validates wallet existence only.async #findAutoTopUpDeploymentSettings(address: string): Promise<AutoTopUpDeployment[]> { const userWallet = await this.userWalletRepository.findOneBy({ address }); - if (!userWallet?.address) { + if (!userWallet) { return []; } return this.deploymentSettingRepository.findAutoTopUpDeploymentsByOwner(address); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts(3 hunks)apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx(6 hunks)apps/deploy-web/src/queries/index.ts(1 hunks)apps/deploy-web/src/services/app-di-container/app-di-container.ts(2 hunks)packages/http-sdk/src/deployment/managed-deployment-http.service.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/deploy-web/src/queries/index.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
apps/deploy-web/src/services/app-di-container/app-di-container.tsapps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsxapps/api/src/deployment/services/draining-deployment/draining-deployment.service.tspackages/http-sdk/src/deployment/managed-deployment-http.service.ts
🧠 Learnings (2)
📚 Learning: 2025-11-19T16:13:43.249Z
Learnt from: stalniy
Repo: akash-network/console PR: 2255
File: apps/api/src/middlewares/privateMiddleware.ts:5-9
Timestamp: 2025-11-19T16:13:43.249Z
Learning: In the Akash Console API (apps/api), avoid resolving DI container dependencies at module scope (module initialization time) to prevent side effects. Instead, resolve dependencies inside functions/methods where they are actually used, even if this means resolving on every invocation, to maintain explicit control over when side effects occur and improve testability.
Applied to files:
apps/deploy-web/src/services/app-di-container/app-di-container.ts
📚 Learning: 2025-06-05T21:07:51.985Z
Learnt from: baktun14
Repo: akash-network/console PR: 1432
File: apps/deploy-web/src/components/deployments/DeploymentAlerts/DeploymentCloseAlert.tsx:38-38
Timestamp: 2025-06-05T21:07:51.985Z
Learning: The ContactPointSelect component in apps/deploy-web/src/components/alerts/ContactPointSelectForm/ContactPointSelect.tsx uses the useFormContext hook internally to connect to React Hook Form, so it doesn't need to be wrapped in a FormField component.
Applied to files:
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx
🧬 Code graph analysis (4)
apps/deploy-web/src/services/app-di-container/app-di-container.ts (4)
packages/http-sdk/src/index.ts (1)
createHttpClient(28-28)apps/deploy-web/src/services/auth/auth/auth.service.ts (1)
withUserToken(69-79)apps/deploy-web/src/services/auth/auth/interceptors.ts (1)
withUserToken(15-25)packages/http-sdk/src/deployment/managed-deployment-http.service.ts (1)
ManagedDeploymentHttpService(10-21)
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx (4)
apps/deploy-web/src/queries/useDeploymentQueries.ts (1)
useWeeklyDeploymentCostQuery(7-16)apps/deploy-web/src/queries/useWalletSettingsQueries.tsx (1)
useWalletSettingsMutations(20-56)packages/ui/context/PopupProvider/PopupProvider.tsx (1)
usePopup(140-146)packages/http-sdk/src/wallet-settings/wallet-settings-http.service.ts (2)
createWalletSettings(15-17)updateWalletSettings(19-21)
apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (3)
apps/api/src/utils/constants.ts (1)
averageBlockCountInAnHour(8-8)apps/api/src/deployment/repositories/deployment-setting/deployment-setting.repository.ts (1)
AutoTopUpDeployment(18-24)apps/api/src/deployment/repositories/lease/lease.repository.ts (1)
DrainingDeploymentOutput(7-14)
packages/http-sdk/src/deployment/managed-deployment-http.service.ts (1)
packages/http-sdk/src/index.ts (1)
HttpClient(28-28)
⏰ 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). (8)
- 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: test-build
- GitHub Check: Validate local packages
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
packages/http-sdk/src/deployment/managed-deployment-http.service.ts (1)
1-21: LGTM!The implementation correctly uses constructor injection with
HttpClient(as suggested in previous review), and the JSDoc now accurately reflects that the method returns the weekly cost in USD. The response structure handling withextractDatais appropriate.apps/api/src/deployment/services/draining-deployment/draining-deployment.service.ts (1)
163-192: LGTM! Weekly cost calculation logic is correct.The method properly:
- Applies authorization via
accessibleByon both wallet and deployment settings- Uses
Number.MAX_SAFE_INTEGERto capture all deployments regardless of predicted close height- Filters to only active deployments with positive block rates
- Converts the accumulated credit cost to fiat at the end
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx (2)
33-70: Good addition of confirmation dialog.The confirmation flow properly:
- Presents context-appropriate messages for enable vs. disable actions
- Prevents state changes if user cancels
- Correctly includes
confirmin the dependency array
135-143: LGTM!The conditional rendering correctly distinguishes between loading state and zero cost (both valid scenarios where
weeklyCost !== undefinedis essential). The currency formatting usingFormattedNumberis appropriate.apps/deploy-web/src/services/app-di-container/app-di-container.ts (1)
95-100: LGTM!The
managedDeploymentfactory correctly:
- Uses the pattern requested in previous reviews (passing
HttpClientto constructor rather than extendingApiHttpService)- Follows the lazy resolution pattern via factory function (per learnings about avoiding module-scope DI resolution)
- Applies the
withUserTokeninterceptor for authenticated requests
refs #1779
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.