Skip to content

refactor(wallet): remove dead self-custody branches from deploy-web consumers#3243

Merged
baktun14 merged 3 commits into
mainfrom
refactor/deploy-web-remove-dual-mode-wallet-branches
Jun 3, 2026
Merged

refactor(wallet): remove dead self-custody branches from deploy-web consumers#3243
baktun14 merged 3 commits into
mainfrom
refactor/deploy-web-remove-dual-mode-wallet-branches

Conversation

@baktun14
Copy link
Copy Markdown
Contributor

@baktun14 baktun14 commented May 29, 2026

Why

L-1 (#3239) collapsed signAndBroadcastTx to managed-only and dropped switchWalletType from the context value, but intentionally kept the wallet-layer artifacts alive — selectedWalletType atom, walletUtils custodial helpers, isCustodial/isManaged on useWallet(), all cosmos-kit reads inside WalletProvider. This PR picks up that cascade: it deletes the dual-mode wallet primitives, the WalletProvider custodial branch, and every consumer that still branched on them. After L-2, the codebase no longer carries the dual-mode contract anywhere — which unblocks L-3 (remove cosmos-kit deps) and L-4 (remove the self_custody feature flag).

Fixes CON-408
Part of Self-custody wallet extraction

PR base is refactor/deploy-web-wallet-provider-managed-only (L-1, #3239) — GitHub will auto-retarget to main after L-1 merges.

What

Bucket A — WalletProvider collapse

  • Drop useSelectedChain(), useManager(), custodialWalletManager, and the CURRENT_WALLET_KEY import/logout side effect
  • Collapse (selectedWalletType === "managed" && managedWallet) || userWallet to just managedWallet
  • Drop the custodial analytics branch; keep the managed identify({ managedWallet: true }) call
  • Remove isCustodial from ContextType and the context value; tighten ManagedWalletMarker (now always { isManaged: true; denom: string })
  • Delete useEnforceSelfCustodyFlag hook + spec (its SelectedWalletType input dies with the atom — the rest of the flag plumbing stays for L-4)

Bucket B — walletStore

  • Delete SelectedWalletType type and the selectedWalletType atom
  • Simplify deriveWalletIsLoading signature (no selectedWalletType / isCustodialConnecting) and its spec
  • Drop the auto-switch effect and getSelectedStorageWallet() usage in useManagedWallet

Bucket C — walletUtils

  • Delete CustodialLocalWallet, the LocalWallet union, getStorageWallets, updateStorageWallets, updateWallet, deleteWalletFromStorage, getSelectedStorageWallet, useSelectedWalletFromStorage
  • Generalize updateStorageManagedWallet to { userId } & Partial<…> so callers (e.g. JWT writes) can update a single field without re-passing the full shape
  • Rewrite ensureUserManagedWalletOwnership to read/write via the managed helpers
  • Re-baseline walletUtils.spec.ts (dual-mode scenarios removed), tests/seeders/localWallet.ts (drop buildCustodialLocalWallet)

Bucket D — consumer collapses

  • useWallet() contract: drop isCustodial, switchWalletType; isManaged becomes literal true
  • Consumers: deploymentSettingsQuery, Sidebar, AccountMenu, ManifestEdit (denom branching + dead PrerequisiteList path), SdlBuilder, SimpleServiceFormControl (drop unused TokenFormControl), OnboardingContainer, useProviderJwt (switch to managed helpers, look up by userId via useUser), PriceEstimateTooltip, DeploymentSubHeader, WalletStatus, DeploymentDetailTopBar, ManifestUpdate, useApiKeysQuery
  • Trim specs that mocked the removed fields

Out of scope (per plan)

  • @cosmos-kit/* / @cosmjs/* dep removal → L-3 (CON-259)
  • self_custody feature-flag config + useIsSelfCustodyEnabled → L-4 (CON-338)
  • Purging legacy {networkId}/wallets and CURRENT_WALLET_KEY localStorage entries → future localStorage sweep
  • RPC polling → /v1/blockchain-status → L-5 (CON-373)
  • JWT cookie auth on provider WS → L-6 (CON-374)

Verification

# Acceptance grep — zero matches in src/
rg -nw 'isCustodial|switchWalletType|selectedWalletType|CustodialLocalWallet' src/
rg -n 'cosmos-kit-jotai|useSelectedChain|useManager' src/context/WalletProvider/

Both pass. npx tsc --noEmit and npm run lint -- --quiet produce no new errors beyond L-1 baseline. npm test passes all suites except a pre-existing TrendIndicator snapshot drift unrelated to this PR.

Net: +412 / −2005.

Summary by CodeRabbit

  • New Features

    • Auto top-up controls and indicators now render consistently.
  • Changes

    • Wallet experience streamlined to a managed-only flow; denominations and balances are displayed consistently.
    • Billing, Alerts and menu items rely on feature flags and account presence (fewer wallet-type conditions).
    • Trial labels and balances appear more consistently across account dropdowns and status areas.
    • Deployment creation and SDL handling simplified and unified.
  • Removed

    • Legacy self-custody/prerequisite flows and the inline token selector.

@baktun14 baktun14 requested a review from a team as a code owner May 29, 2026 21:13
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5bb0891c-a32a-4270-a77a-75b7b8e5411e

📥 Commits

Reviewing files that changed from the base of the PR and between de2e0be and fd66c0c.

📒 Files selected for processing (43)
  • .eslintrc.js
  • apps/deploy-web/src/components/deployments/DeploymentDetailTopBar/DeploymentDetailTopBar.spec.tsx
  • apps/deploy-web/src/components/deployments/DeploymentDetailTopBar/DeploymentDetailTopBar.tsx
  • apps/deploy-web/src/components/deployments/DeploymentSubHeader.tsx
  • apps/deploy-web/src/components/deployments/ManifestUpdate/ManifestUpdate.spec.tsx
  • apps/deploy-web/src/components/deployments/ManifestUpdate/ManifestUpdate.tsx
  • apps/deploy-web/src/components/home/YourAccount/YourAccount.spec.tsx
  • apps/deploy-web/src/components/layout/AccountMenu.spec.tsx
  • apps/deploy-web/src/components/layout/AccountMenu.tsx
  • apps/deploy-web/src/components/layout/Sidebar.tsx
  • apps/deploy-web/src/components/layout/WalletStatus.spec.tsx
  • apps/deploy-web/src/components/layout/WalletStatus.tsx
  • apps/deploy-web/src/components/new-deployment/CreateLease/CreateLease.spec.tsx
  • apps/deploy-web/src/components/new-deployment/ManifestEdit/ManifestEdit.spec.tsx
  • apps/deploy-web/src/components/new-deployment/ManifestEdit/ManifestEdit.tsx
  • apps/deploy-web/src/components/new-deployment/SdlBuilder.spec.tsx
  • apps/deploy-web/src/components/new-deployment/SdlBuilder.tsx
  • apps/deploy-web/src/components/onboarding/OnboardingContainer/OnboardingContainer.tsx
  • apps/deploy-web/src/components/sdl/SimpleServiceFormControl.tsx
  • apps/deploy-web/src/components/sdl/TokenFormControl.tsx
  • apps/deploy-web/src/components/shared/PrerequisiteList.tsx
  • apps/deploy-web/src/components/shared/PriceEstimateTooltip.tsx
  • apps/deploy-web/src/components/wallet/ConnectManagedWalletButton.spec.tsx
  • apps/deploy-web/src/components/wallet/ConnectManagedWalletButton.tsx
  • apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx
  • apps/deploy-web/src/context/WalletProvider/deriveWalletIsLoading.spec.ts
  • apps/deploy-web/src/context/WalletProvider/deriveWalletIsLoading.ts
  • apps/deploy-web/src/context/WalletProvider/useEnforceSelfCustodyFlag.spec.ts
  • apps/deploy-web/src/context/WalletProvider/useEnforceSelfCustodyFlag.ts
  • apps/deploy-web/src/context/WalletProvider/useSignAndBroadcast.tsx
  • apps/deploy-web/src/hooks/useManagedWallet.ts
  • apps/deploy-web/src/hooks/useProviderJwt/useProviderJwt.spec.tsx
  • apps/deploy-web/src/hooks/useProviderJwt/useProviderJwt.ts
  • apps/deploy-web/src/hooks/useSelectedChain/useSelectedChain.ts
  • apps/deploy-web/src/queries/deploymentSettingsQuery.spec.ts
  • apps/deploy-web/src/queries/deploymentSettingsQuery.ts
  • apps/deploy-web/src/queries/useApiKeysQuery.spec.tsx
  • apps/deploy-web/src/queries/useApiKeysQuery.ts
  • apps/deploy-web/src/store/walletStore.ts
  • apps/deploy-web/src/utils/walletUtils.spec.ts
  • apps/deploy-web/src/utils/walletUtils.ts
  • apps/deploy-web/tests/seeders/localWallet.ts
  • apps/deploy-web/tests/seeders/wallet.ts
💤 Files with no reviewable changes (9)
  • apps/deploy-web/src/hooks/useSelectedChain/useSelectedChain.ts
  • apps/deploy-web/src/components/sdl/TokenFormControl.tsx
  • apps/deploy-web/src/store/walletStore.ts
  • apps/deploy-web/src/context/WalletProvider/useEnforceSelfCustodyFlag.ts
  • apps/deploy-web/src/components/sdl/SimpleServiceFormControl.tsx
  • apps/deploy-web/src/components/shared/PrerequisiteList.tsx
  • apps/deploy-web/src/context/WalletProvider/useEnforceSelfCustodyFlag.spec.ts
  • apps/deploy-web/src/components/wallet/ConnectManagedWalletButton.tsx
  • apps/deploy-web/src/components/wallet/ConnectManagedWalletButton.spec.tsx
✅ Files skipped from review due to trivial changes (1)
  • apps/deploy-web/src/components/shared/PriceEstimateTooltip.tsx
🚧 Files skipped from review as they are similar to previous changes (32)
  • apps/deploy-web/src/components/new-deployment/SdlBuilder.spec.tsx
  • .eslintrc.js
  • apps/deploy-web/tests/seeders/wallet.ts
  • apps/deploy-web/src/context/WalletProvider/deriveWalletIsLoading.spec.ts
  • apps/deploy-web/src/components/deployments/ManifestUpdate/ManifestUpdate.spec.tsx
  • apps/deploy-web/src/queries/useApiKeysQuery.ts
  • apps/deploy-web/src/components/home/YourAccount/YourAccount.spec.tsx
  • apps/deploy-web/src/components/onboarding/OnboardingContainer/OnboardingContainer.tsx
  • apps/deploy-web/src/components/deployments/DeploymentDetailTopBar/DeploymentDetailTopBar.spec.tsx
  • apps/deploy-web/src/hooks/useProviderJwt/useProviderJwt.ts
  • apps/deploy-web/src/components/new-deployment/CreateLease/CreateLease.spec.tsx
  • apps/deploy-web/src/components/new-deployment/SdlBuilder.tsx
  • apps/deploy-web/src/context/WalletProvider/deriveWalletIsLoading.ts
  • apps/deploy-web/src/context/WalletProvider/useSignAndBroadcast.tsx
  • apps/deploy-web/src/hooks/useManagedWallet.ts
  • apps/deploy-web/src/components/deployments/ManifestUpdate/ManifestUpdate.tsx
  • apps/deploy-web/src/queries/deploymentSettingsQuery.ts
  • apps/deploy-web/src/components/layout/WalletStatus.tsx
  • apps/deploy-web/src/components/layout/WalletStatus.spec.tsx
  • apps/deploy-web/tests/seeders/localWallet.ts
  • apps/deploy-web/src/components/layout/AccountMenu.tsx
  • apps/deploy-web/src/components/deployments/DeploymentDetailTopBar/DeploymentDetailTopBar.tsx
  • apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx
  • apps/deploy-web/src/queries/deploymentSettingsQuery.spec.ts
  • apps/deploy-web/src/components/layout/Sidebar.tsx
  • apps/deploy-web/src/components/layout/AccountMenu.spec.tsx
  • apps/deploy-web/src/components/new-deployment/ManifestEdit/ManifestEdit.spec.tsx
  • apps/deploy-web/src/components/deployments/DeploymentSubHeader.tsx
  • apps/deploy-web/src/components/new-deployment/ManifestEdit/ManifestEdit.tsx
  • apps/deploy-web/src/queries/useApiKeysQuery.spec.tsx
  • apps/deploy-web/src/utils/walletUtils.spec.ts
  • apps/deploy-web/src/hooks/useProviderJwt/useProviderJwt.spec.tsx

📝 Walkthrough

Walkthrough

Consolidates the wallet model to managed-only: removes custodial branches and prerequisites, standardizes managed-wallet storage and JWT flows, switches error reporting to notificator, unconditionally applies denom/audit transformations, and updates tests and UI gating to use flags and authenticated user identity.

Changes

Managed-Wallet-Only Refactor

Layer / File(s) Summary
Configuration and store cleanup
.eslintrc.js, apps/deploy-web/src/store/walletStore.ts
Adds root: true to ESLint config; removes SelectedWalletType/selectedWalletType atom leaving trial/modal/balance atoms.
Managed-wallet storage API & tests
apps/deploy-web/src/utils/walletUtils.ts, apps/deploy-web/src/utils/walletUtils.spec.ts, apps/deploy-web/tests/seeders/localWallet.ts, apps/deploy-web/tests/seeders/wallet.ts
Exports ManagedLocalWallet; updateStorageManagedWallet accepts partial updates with creation validation and returns `ManagedLocalWallet
WalletProvider & loading model
apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx, apps/deploy-web/src/context/WalletProvider/deriveWalletIsLoading.ts, apps/deploy-web/src/context/WalletProvider/deriveWalletIsLoading.spec.ts
Provider now derives identity/loading from useManagedWallet/useUser, context always reports isManaged: true and denom; logout/load simplified; deriveWalletIsLoading reduced to (hasAuthenticatedUserId && isManagedWalletLoading).
Signing and JWT flow
apps/deploy-web/src/context/WalletProvider/useSignAndBroadcast.tsx, apps/deploy-web/src/hooks/useProviderJwt/useProviderJwt.ts, apps/deploy-web/src/hooks/useProviderJwt/useProviderJwt.spec.tsx
Error reporting uses useNotificator.error; Add-Credits snackbar simplified; useProviderJwt hydrates token from managed storage by userId, requires userId for generation, always requests server-signed JWT and persists via updateStorageManagedWallet; tests adjusted.
Query hooks: remove managed gating
apps/deploy-web/src/queries/deploymentSettingsQuery.ts, apps/deploy-web/src/queries/deploymentSettingsQuery.spec.ts, apps/deploy-web/src/queries/useApiKeysQuery.ts, apps/deploy-web/src/queries/useApiKeysQuery.spec.tsx
useDeploymentSettingQuery and API-keys hooks no longer require wallet.isManaged; queries enabled by dseq or user?.userId only; update mutation no longer throws for unmanaged case.
Layout & account surfaces
apps/deploy-web/src/components/layout/AccountMenu.tsx, apps/deploy-web/src/components/layout/Sidebar.tsx, apps/deploy-web/src/components/layout/WalletStatus.tsx, related specs
Remove wallet.isManaged gating for Billing & Usage and Alerts; WalletStatus uses managed grants USD and isTrialing for Trial label; DI cleaned; tests updated.
Deployment detail surfaces
apps/deploy-web/src/components/deployments/DeploymentSubHeader.tsx, apps/deploy-web/src/components/deployments/DeploymentDetailTopBar/DeploymentDetailTopBar.tsx, apps/deploy-web/src/components/deployments/ManifestUpdate/ManifestUpdate.tsx, related specs
Remove custodial tooltip blocks; auto top-up renders unconditionally; manifest update snackbar flow simplified; tests expect managed state.
Deployment creation & SDL
apps/deploy-web/src/components/new-deployment/ManifestEdit/ManifestEdit.tsx, apps/deploy-web/src/components/new-deployment/SdlBuilder.tsx, apps/deploy-web/src/components/sdl/SimpleServiceFormControl.tsx, apps/deploy-web/src/components/sdl/TokenFormControl.tsx (removed), related specs
Removed PrerequisiteList and its modal; always append auditor requirement and replace SDL denom with wallet.denom; SdlBuilder always syncs placement pricing denom; TokenFormControl removed; tests updated to managed-wallet storage API.
Onboarding and shared UI
apps/deploy-web/src/components/onboarding/OnboardingContainer/OnboardingContainer.tsx, apps/deploy-web/src/components/shared/PriceEstimateTooltip.tsx, apps/deploy-web/src/components/wallet/ConnectManagedWalletButton.tsx, related specs
Onboarding denom and deposit logic simplified; PriceEstimateTooltip drops custodial-only monthly line; ConnectManagedWalletButton DI simplified (removed useFlag).

🎯 4 (Complex) | ⏱️ ~60 minutes

  • akash-network/console#3239: The main PR and retrieved PR both modify the managed-wallet signing/broadcasting path—main PR updates apps/deploy-web/src/context/WalletProvider/useSignAndBroadcast.tsx and related WalletProvider behavior, which is exactly what the retrieved PR introduces/refactors via signAndBroadcast/useSignAndBroadcast.
  • akash-network/console#3227: Both PRs refactor apps/deploy-web/src/components/layout/WalletStatus.tsx to drop custodial/managed branching in favor of managed-only wallet dropdown behavior.
  • akash-network/console#3217: Overlaps useProviderJwt changes (JWT generation/persistence flow).

Suggested reviewers:

  • ygrishajev
  • stalniy
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/deploy-web-remove-dual-mode-wallet-branches

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

Base automatically changed from refactor/deploy-web-wallet-provider-managed-only to main June 3, 2026 15:19
@baktun14 baktun14 force-pushed the refactor/deploy-web-remove-dual-mode-wallet-branches branch from 30fa3bc to c31eb62 Compare June 3, 2026 16:29
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 3, 2026

Codecov Report

❌ Patch coverage is 68.75000% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.62%. Comparing base (ccba7d8) to head (fd66c0c).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...-web/src/context/WalletProvider/WalletProvider.tsx 0.00% 13 Missing and 3 partials ⚠️
...src/context/WalletProvider/useSignAndBroadcast.tsx 20.00% 3 Missing and 1 partial ⚠️
apps/deploy-web/src/utils/walletUtils.ts 90.90% 3 Missing ⚠️
...nents/new-deployment/ManifestEdit/ManifestEdit.tsx 66.66% 2 Missing ⚠️
...loy-web/src/hooks/useProviderJwt/useProviderJwt.ts 87.50% 2 Missing ⚠️
...src/components/deployments/DeploymentSubHeader.tsx 0.00% 1 Missing ⚠️
apps/deploy-web/src/components/layout/Sidebar.tsx 0.00% 0 Missing and 1 partial ⚠️
...y-web/src/components/new-deployment/SdlBuilder.tsx 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3243      +/-   ##
==========================================
- Coverage   67.78%   66.62%   -1.17%     
==========================================
  Files        1077      988      -89     
  Lines       26303    23955    -2348     
  Branches     6318     5809     -509     
==========================================
- Hits        17830    15959    -1871     
+ Misses       7416     6992     -424     
+ Partials     1057     1004      -53     
Flag Coverage Δ *Carryforward flag
api 84.72% <ø> (ø) Carriedforward from ccba7d8
deploy-web 52.50% <68.75%> (+0.01%) ⬆️
log-collector ?
notifications 91.06% <ø> (ø) Carriedforward from ccba7d8
provider-console 81.38% <ø> (ø) Carriedforward from ccba7d8
provider-inventory ?
provider-proxy 86.37% <ø> (ø) Carriedforward from ccba7d8
tx-signer ?

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

Files with missing lines Coverage Δ
.../DeploymentDetailTopBar/DeploymentDetailTopBar.tsx 66.33% <100.00%> (-0.66%) ⬇️
...ents/deployments/ManifestUpdate/ManifestUpdate.tsx 89.41% <100.00%> (+1.36%) ⬆️
...s/deploy-web/src/components/layout/AccountMenu.tsx 79.31% <100.00%> (-0.69%) ⬇️
.../deploy-web/src/components/layout/WalletStatus.tsx 100.00% <100.00%> (+4.76%) ⬆️
...arding/OnboardingContainer/OnboardingContainer.tsx 76.80% <100.00%> (-0.37%) ⬇️
...eb/src/components/sdl/SimpleServiceFormControl.tsx 2.02% <ø> (+0.05%) ⬆️
...web/src/components/shared/PriceEstimateTooltip.tsx 22.22% <ø> (+5.55%) ⬆️
...c/components/wallet/ConnectManagedWalletButton.tsx 84.61% <ø> (ø)
...rc/context/WalletProvider/deriveWalletIsLoading.ts 100.00% <100.00%> (ø)
apps/deploy-web/src/hooks/useManagedWallet.ts 3.57% <ø> (+0.79%) ⬆️
... and 11 more

... and 87 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
Copy Markdown
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 (1)
apps/deploy-web/src/components/deployments/ManifestUpdate/ManifestUpdate.tsx (1)

128-176: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Don't surface provider/send failures as SDL parse errors.

Any error from signAndBroadcastTx() or sendManifest() currently falls through to setParsingError("Error while parsing SDL file"), so network/auth/provider failures get mislabeled as editor parse errors. Keep parsingError for YAML/validation failures only, and let operational failures stay on the snackbar path.

Suggested fix
     } catch (error: any) {
       if (error.name === "YAMLException" || error.name === "CustomValidationError") {
         setParsingError(error.message);
       } else {
-        setParsingError("Error while parsing SDL file");
         console.error(error);
       }
       setIsSendingManifest(false);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/deploy-web/src/components/deployments/ManifestUpdate/ManifestUpdate.tsx`
around lines 128 - 176, The catch block in handleUpdateClick is treating all
exceptions as parse errors; only YAMLException and CustomValidationError should
setParsingError — operational failures from signAndBroadcastTx or sendManifest
should be propagated to the app-level/snackbar path. Change the catch so that if
error.name is "YAMLException" or "CustomValidationError" you call
setParsingError(error.message), otherwise clear any parsing error/state (or
leave it unchanged), ensure setIsSendingManifest(false) is executed, log the
error if desired, and rethrow the error (or return/propagate it) so
signAndBroadcastTx/sendManifest failures are handled by the global/snackbar
error handler; keep references to handleUpdateClick, signAndBroadcastTx,
sendManifest, setParsingError, and setIsSendingManifest to locate and update the
code.
🧹 Nitpick comments (3)
apps/deploy-web/src/queries/useApiKeysQuery.spec.tsx (1)

105-109: ⚡ Quick win

Avoid nested user overrides inside mock() here.

vitest-mock-extended can proxy nested overrides, so unresolved user.* fields may become mock functions instead of undefined. Build the mock first, then assign user and isLoading on the returned object.

Suggested pattern
- useUser: () =>
-   mock<ReturnType<typeof USE_API_KEYS_DEPENDENCIES.useUser>>({
-     user: mockUser,
-     isLoading: false
-   })
+ useUser: () => {
+   const useUserResult = mock<ReturnType<typeof USE_API_KEYS_DEPENDENCIES.useUser>>();
+   useUserResult.user = mockUser;
+   useUserResult.isLoading = false;
+   return useUserResult;
+ }

Based on learnings: when using vitest-mock-extended, avoid passing nested objects as overrides to mock<T>() because recursive proxies can turn unknown properties into mock functions; assign nested properties after creating the mock instead.

Also applies to: 153-157, 201-205, 231-235

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/deploy-web/src/queries/useApiKeysQuery.spec.tsx` around lines 105 - 109,
The test is passing a nested override object into mock<ReturnType<typeof
USE_API_KEYS_DEPENDENCIES.useUser>>() which lets vitest-mock-extended proxy
nested fields into mock functions; instead, create the base mock first (e.g.,
const userHook = mock<ReturnType<typeof USE_API_KEYS_DEPENDENCIES.useUser>>() ),
then assign userHook.user = mockUser and userHook.isLoading = false and return
userHook from the useUser override. Apply the same pattern to the other
occurrences referenced (around lines 153-157, 201-205, 231-235) so nested
properties are set after creating the mock.
apps/deploy-web/src/components/layout/AccountMenu.spec.tsx (2)

84-95: ⚡ Quick win

Avoid the nested mock() override for useCustomUser.

vitest-mock-extended can proxy nested overrides like user: { ... }, which makes future missing fields read back as mock functions instead of undefined. Returning a plain hook result here is safer.

Safer setup
     const dependencies: typeof DEPENDENCIES = {
-      useCustomUser: () =>
-        mock<ReturnType<typeof DEPENDENCIES.useCustomUser>>({
-          user: input.username ? { username: input.username, userId: input.userId } : undefined,
-          isLoading: input.isLoading ?? false
-        }),
+      useCustomUser: () => ({
+        user: input.username ? { username: input.username, userId: input.userId } : undefined,
+        isLoading: input.isLoading ?? false,
+        error: undefined,
+        checkSession: vi.fn()
+      }),
       useRouter: () => mock<ReturnType<typeof DEPENDENCIES.useRouter>>({ push }),
       useFlag: flagName => (flagName === "billing_usage" && input.isBillingUsageEnabled) ?? false
     };
Based on learnings: when using `vitest-mock-extended`, avoid passing nested objects as overrides to `mock()` because recursive proxies can turn unknown nested properties into mock functions.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/deploy-web/src/components/layout/AccountMenu.spec.tsx` around lines 84 -
95, The test's setup function nests a mock override via mock<ReturnType<typeof
DEPENDENCIES.useCustomUser>>({ user: ... }) which causes vitest-mock-extended to
create proxy mock functions for unknown nested fields; instead, return a plain
object for the useCustomUser hook result (not wrapped by mock) inside setup,
e.g. replace the mock<ReturnType<typeof DEPENDENCIES.useCustomUser>>(...) return
with an actual object matching the hook shape (providing user and isLoading) so
unknown nested properties remain undefined; keep useRouter and useFlag mocks
as-is and reference setup, DEPENDENCIES.useCustomUser, useCustomUser, useRouter,
and useFlag when making the change.

59-81: ⚡ Quick win

Add the missing flag=true / userId-absent regression test.

This change makes user?.userId part of the render contract, but the suite only covers the happy path and flag=false. A regression that shows Billing & Usage for users without an internal account would still pass here.

Proposed test
+  it("hides Billing & Usage when the user has no internal account yet", async () => {
+    setup({
+      username: "erin",
+      isBillingUsageEnabled: true
+    });
+
+    await userEvent.click(screen.getByRole("button", { name: /account menu/i }));
+
+    await screen.findByText("Logout");
+    expect(screen.queryByText("Billing & Usage")).not.toBeInTheDocument();
+  });
Based on learnings: `user.userId` is the field used to determine whether an internal account exists and should be the onboarding/auth-state guard.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/deploy-web/src/components/layout/AccountMenu.spec.tsx` around lines 59 -
81, Add a regression test to cover the case where isBillingUsageEnabled is true
but the user lacks an internal account (user.userId is undefined); update
AccountMenu.spec.tsx by adding a new it block (similar style to existing tests)
that calls setup({ username: "eve", /* no userId */, isBillingUsageEnabled: true
}), opens the account menu via userEvent.click(screen.getByRole("button", {
name: /account menu/i })), and asserts that "Billing & Usage" is NOT in the
document, ensuring the component uses user?.userId as the guard.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/deploy-web/src/components/deployments/DeploymentDetailTopBar/DeploymentDetailTopBar.spec.tsx`:
- Around line 112-118: The test "renders auto top-up section" currently only
asserts the static label via screen.getByText; update it to also assert the
interactive switch control itself (e.g., use screen.getByRole('switch', { name:
/auto top-up/i }) or screen.getByLabelText(/auto top-up/i)) so the test fails if
the switch is removed or not rendered. Modify the test that calls setup({
deployment: createDeployment({ state: "active" }) }) to include an additional
expectation asserting the switch control is in the document and optionally that
it has the expected checked state.

---

Outside diff comments:
In
`@apps/deploy-web/src/components/deployments/ManifestUpdate/ManifestUpdate.tsx`:
- Around line 128-176: The catch block in handleUpdateClick is treating all
exceptions as parse errors; only YAMLException and CustomValidationError should
setParsingError — operational failures from signAndBroadcastTx or sendManifest
should be propagated to the app-level/snackbar path. Change the catch so that if
error.name is "YAMLException" or "CustomValidationError" you call
setParsingError(error.message), otherwise clear any parsing error/state (or
leave it unchanged), ensure setIsSendingManifest(false) is executed, log the
error if desired, and rethrow the error (or return/propagate it) so
signAndBroadcastTx/sendManifest failures are handled by the global/snackbar
error handler; keep references to handleUpdateClick, signAndBroadcastTx,
sendManifest, setParsingError, and setIsSendingManifest to locate and update the
code.

---

Nitpick comments:
In `@apps/deploy-web/src/components/layout/AccountMenu.spec.tsx`:
- Around line 84-95: The test's setup function nests a mock override via
mock<ReturnType<typeof DEPENDENCIES.useCustomUser>>({ user: ... }) which causes
vitest-mock-extended to create proxy mock functions for unknown nested fields;
instead, return a plain object for the useCustomUser hook result (not wrapped by
mock) inside setup, e.g. replace the mock<ReturnType<typeof
DEPENDENCIES.useCustomUser>>(...) return with an actual object matching the hook
shape (providing user and isLoading) so unknown nested properties remain
undefined; keep useRouter and useFlag mocks as-is and reference setup,
DEPENDENCIES.useCustomUser, useCustomUser, useRouter, and useFlag when making
the change.
- Around line 59-81: Add a regression test to cover the case where
isBillingUsageEnabled is true but the user lacks an internal account
(user.userId is undefined); update AccountMenu.spec.tsx by adding a new it block
(similar style to existing tests) that calls setup({ username: "eve", /* no
userId */, isBillingUsageEnabled: true }), opens the account menu via
userEvent.click(screen.getByRole("button", { name: /account menu/i })), and
asserts that "Billing & Usage" is NOT in the document, ensuring the component
uses user?.userId as the guard.

In `@apps/deploy-web/src/queries/useApiKeysQuery.spec.tsx`:
- Around line 105-109: The test is passing a nested override object into
mock<ReturnType<typeof USE_API_KEYS_DEPENDENCIES.useUser>>() which lets
vitest-mock-extended proxy nested fields into mock functions; instead, create
the base mock first (e.g., const userHook = mock<ReturnType<typeof
USE_API_KEYS_DEPENDENCIES.useUser>>() ), then assign userHook.user = mockUser
and userHook.isLoading = false and return userHook from the useUser override.
Apply the same pattern to the other occurrences referenced (around lines
153-157, 201-205, 231-235) so nested properties are set after creating the mock.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c0838dfd-3215-4dfa-b6cc-5533f6372c7d

📥 Commits

Reviewing files that changed from the base of the PR and between c3c1f2e and c31eb62.

📒 Files selected for processing (41)
  • .eslintrc.js
  • apps/deploy-web/src/components/deployments/DeploymentDetailTopBar/DeploymentDetailTopBar.spec.tsx
  • apps/deploy-web/src/components/deployments/DeploymentDetailTopBar/DeploymentDetailTopBar.tsx
  • apps/deploy-web/src/components/deployments/DeploymentSubHeader.tsx
  • apps/deploy-web/src/components/deployments/ManifestUpdate/ManifestUpdate.spec.tsx
  • apps/deploy-web/src/components/deployments/ManifestUpdate/ManifestUpdate.tsx
  • apps/deploy-web/src/components/home/YourAccount/YourAccount.spec.tsx
  • apps/deploy-web/src/components/layout/AccountMenu.spec.tsx
  • apps/deploy-web/src/components/layout/AccountMenu.tsx
  • apps/deploy-web/src/components/layout/Sidebar.tsx
  • apps/deploy-web/src/components/layout/WalletStatus.spec.tsx
  • apps/deploy-web/src/components/layout/WalletStatus.tsx
  • apps/deploy-web/src/components/new-deployment/CreateLease/CreateLease.spec.tsx
  • apps/deploy-web/src/components/new-deployment/ManifestEdit/ManifestEdit.spec.tsx
  • apps/deploy-web/src/components/new-deployment/ManifestEdit/ManifestEdit.tsx
  • apps/deploy-web/src/components/new-deployment/SdlBuilder.spec.tsx
  • apps/deploy-web/src/components/new-deployment/SdlBuilder.tsx
  • apps/deploy-web/src/components/onboarding/OnboardingContainer/OnboardingContainer.tsx
  • apps/deploy-web/src/components/sdl/SimpleServiceFormControl.tsx
  • apps/deploy-web/src/components/sdl/TokenFormControl.tsx
  • apps/deploy-web/src/components/shared/PriceEstimateTooltip.tsx
  • apps/deploy-web/src/components/wallet/ConnectManagedWalletButton.spec.tsx
  • apps/deploy-web/src/components/wallet/ConnectManagedWalletButton.tsx
  • apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx
  • apps/deploy-web/src/context/WalletProvider/deriveWalletIsLoading.spec.ts
  • apps/deploy-web/src/context/WalletProvider/deriveWalletIsLoading.ts
  • apps/deploy-web/src/context/WalletProvider/useEnforceSelfCustodyFlag.spec.ts
  • apps/deploy-web/src/context/WalletProvider/useEnforceSelfCustodyFlag.ts
  • apps/deploy-web/src/context/WalletProvider/useSignAndBroadcast.tsx
  • apps/deploy-web/src/hooks/useManagedWallet.ts
  • apps/deploy-web/src/hooks/useProviderJwt/useProviderJwt.spec.tsx
  • apps/deploy-web/src/hooks/useProviderJwt/useProviderJwt.ts
  • apps/deploy-web/src/queries/deploymentSettingsQuery.spec.ts
  • apps/deploy-web/src/queries/deploymentSettingsQuery.ts
  • apps/deploy-web/src/queries/useApiKeysQuery.spec.tsx
  • apps/deploy-web/src/queries/useApiKeysQuery.ts
  • apps/deploy-web/src/store/walletStore.ts
  • apps/deploy-web/src/utils/walletUtils.spec.ts
  • apps/deploy-web/src/utils/walletUtils.ts
  • apps/deploy-web/tests/seeders/localWallet.ts
  • apps/deploy-web/tests/seeders/wallet.ts
💤 Files with no reviewable changes (7)
  • apps/deploy-web/src/store/walletStore.ts
  • apps/deploy-web/src/components/sdl/TokenFormControl.tsx
  • apps/deploy-web/src/context/WalletProvider/useEnforceSelfCustodyFlag.spec.ts
  • apps/deploy-web/src/components/wallet/ConnectManagedWalletButton.tsx
  • apps/deploy-web/src/context/WalletProvider/useEnforceSelfCustodyFlag.ts
  • apps/deploy-web/src/components/wallet/ConnectManagedWalletButton.spec.tsx
  • apps/deploy-web/src/components/sdl/SimpleServiceFormControl.tsx

@baktun14 baktun14 force-pushed the refactor/deploy-web-remove-dual-mode-wallet-branches branch from c31eb62 to dc4149b Compare June 3, 2026 16:45
baktun14 added 3 commits June 3, 2026 13:02
…onsumers

Drops the dual-mode wallet primitives that L-1 intentionally left in
place: the `selectedWalletType` atom, the `walletUtils` custodial
helpers, the `LocalWallet` union, `isCustodial`/`switchWalletType` on
the `useWallet()` contract, and every consumer that still branched on
them. Also removes the cosmos-kit reads (`useSelectedChain`,
`useManager`, `CURRENT_WALLET_KEY`) and custodial analytics branch
inside `WalletProvider` itself, plus `useEnforceSelfCustodyFlag`
whose input type died with the atom. Legacy `{networkId}/wallets`
storage entries are deliberately left as inert data — a separate
project sweeps localStorage. Unblocks L-3 (cosmos-kit removal) and
L-4 (self_custody flag removal).

Also sets `root: true` in the monorepo's ESLint config so working in
git worktrees nested under the repo doesn't trip the "plugin loaded
twice" error.

Fixes CON-408
…lf-custody branches

Replaces the duplicated transaction-error snackbar wiring in
useSignAndBroadcast with the existing useNotificator helper, and swaps
the inline Add Funds <Link> for AddFundsLink so the verified-login gate
is back in place. Also removes branches that are unreachable now that
deploy-web is managed-wallet-only (uakt denom guard, useFlag dependency
in ConnectManagedWalletButton) and trims a stale narration comment in
WalletProvider.
@baktun14 baktun14 force-pushed the refactor/deploy-web-remove-dual-mode-wallet-branches branch from de2e0be to fd66c0c Compare June 3, 2026 17:03
@baktun14 baktun14 merged commit f5e0804 into main Jun 3, 2026
57 checks passed
@baktun14 baktun14 deleted the refactor/deploy-web-remove-dual-mode-wallet-branches branch June 3, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant